【问题标题】:How can I draw a red circle around blobs detected in image?如何在图像中检测到的斑点周围画一个红色圆圈?
【发布时间】:2020-02-05 10:45:12
【问题描述】:

我有以下图片:

我想在输出中实现 3 个结果:

  1. 突出显示图像中的黑点/色块,并用红色圆形轮廓围绕它们。
  2. 计算点/补丁的数量
  3. 打印覆盖在图像上的点/补丁的数量。

现在,我只能数出图像中的点/斑块的数量并打印出来:

import cv2

## convert to grayscale
gray = cv2.imread("blue.jpg", 0)

## threshold
th, threshed = cv2.threshold(gray, 100, 255,cv2.THRESH_BINARY_INV|cv2.THRESH_OTSU)

## findcontours
cnts = cv2.findContours(threshed, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[-2]

## filter by area
s1= 3
s2 = 20
xcnts = []
for cnt in cnts:
    if s1<cv2.contourArea(cnt) <s2:
        xcnts.append(cnt)

print("Number of dots: {}".format(len(xcnts)))
>>> Number of dots: 66

但我不知道如何突出显示图像上的补丁。

编辑:以下图片的预期结果:

应该是这样的:

【问题讨论】:

  • 使用drawContours()
  • 请添加第二张标记图像以显示预期结果。谢谢。
  • @MarkSetchell 已编辑以包含示例输出。
  • @Kristada673,提供的图像当然是灰度的

标签: python image opencv image-processing object-detection


【解决方案1】:

drawContours()、convexHull() 或 minEnclosureCircle() 应该可以满足您的需求。 这是一个来自 opencv 的教程,展示了如何做你想做的事情:

https://docs.opencv.org/3.4/da/d0c/tutorial_bounding_rects_circles.html

OpenCV 有很多很棒的教程,所以当你想学习新东西时,请先查看它们 :)

【讨论】:

  • 这会打开 2 个窗口,一个带有原始图像和一个阈值跟踪器,另一个用于突出显示的圆圈。我希望它在同一个窗口中 - 即突出显示补丁的原始图像。
  • 只在原图上画圆圈,不用画图。
  • cv.drawContours(drawing, contours_poly, i, color) cv.circle(drawing, (int(centers[i][0]), int(centers[i][1])), int(radius[i]), color, 2)将此处的绘图更改为您的原始图像的名称
  • 这样,我得到了原始图像上的高光,但跟踪器窗口仍然单独出现。如何让cv.createTrackbar()在原窗口中创建trackbar?
  • 想要轨迹栏吗?还是您只是复制了示例中的所有代码?要将其添加到您的原始图像中,请使用source_window = 'Source' cv.namedWindow(source_window) cv.imshow(source_window, src),然后使用cv.createTrackbar('Canny thresh:', source_window, thresh, max_thresh, thresh_callback),并将它们指向您希望跟踪栏所在的窗口。为避免出现其他窗口,您只需避免创建或显示它。
【解决方案2】:

正如@alkasm 先生所说,您可以使用cv2.drawContours()。因此,您可以在代码末尾添加以下内容:

image = cv2.imread("blue.jpg")
cv2.drawContours(image, cnts,
        contourIdx = -1, 
        color = (0, 255, 0), #green
        thickness = 5)
cv2.imshow('Contours', image) 
cv2.waitKey()

现在,图像将如下所示:

【讨论】:

  • 有没有办法调整阈值,即使是较暗的点也能突出显示?
  • 检查这个link...希望这是你想要的:)
【解决方案3】:

这里有一些方法:

1.颜色阈值

想法是将图像转换为 HSV 格式,然后定义上下颜色阈值以隔离所需的颜色范围。这产生了一个蒙版,我们可以在其中使用cv2.findContours() 找到蒙版上的轮廓,并使用cv2.drawContours() 绘制轮廓

import numpy as np
import cv2

# Color threshold
image = cv2.imread('1.jpg')
original = image.copy()
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower = np.array([0, 0, 127])
upper = np.array([179, 255, 255])
mask = cv2.inRange(hsv, lower, upper)
result = cv2.bitwise_and(original,original,mask=mask)

# Find blob contours on mask
cnts = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(original,[c], -1, (36,255,12), 2)

cv2.imshow('result', result)
cv2.imshow('original', original)
cv2.waitKey()

2。简单阈值

这个想法是阈值并获得二进制掩码。同样,为了突出图像中的补丁,我们使用cv2.drawContours()。为了确定菌落的数量,我们在遍历轮廓时保留一个计数器。最后,为了在图像上打印补丁的数量,我们使用cv2.putText()

殖民地:11

import numpy as np
import cv2

image = cv2.imread('2.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.medianBlur(gray, 5)
thresh = cv2.threshold(blur,100,255,cv2.THRESH_BINARY_INV)[1]

cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
colonies = 0
for c in cnts:
    cv2.drawContours(image, [c], -1, (36,255,12), 2)
    colonies += 1

print("Colonies:", colonies)
cv2.putText(image, 'Colonies: {}'.format(colonies), (0, image.shape[0] - 15), \
        cv2.FONT_HERSHEY_SIMPLEX, 0.8, (36,255,12), 2)

cv2.imshow('thresh', thresh)
cv2.imshow('image', image)
cv2.waitKey()

检测蓝色斑点的颜色阈值也可以工作

lower = np.array([0, 0, 0])
upper = np.array([179, 255, 84])

您可以使用此脚本来确定 HSV 上下颜色范围

import cv2
import sys
import numpy as np

def nothing(x):
    pass

# Load in image
image = cv2.imread('1.jpg')

# Create a window
cv2.namedWindow('image')

# create trackbars for color change
cv2.createTrackbar('HMin','image',0,179,nothing) # Hue is from 0-179 for Opencv
cv2.createTrackbar('SMin','image',0,255,nothing)
cv2.createTrackbar('VMin','image',0,255,nothing)
cv2.createTrackbar('HMax','image',0,179,nothing)
cv2.createTrackbar('SMax','image',0,255,nothing)
cv2.createTrackbar('VMax','image',0,255,nothing)

# Set default value for MAX HSV trackbars.
cv2.setTrackbarPos('HMax', 'image', 179)
cv2.setTrackbarPos('SMax', 'image', 255)
cv2.setTrackbarPos('VMax', 'image', 255)

# Initialize to check if HSV min/max value changes
hMin = sMin = vMin = hMax = sMax = vMax = 0
phMin = psMin = pvMin = phMax = psMax = pvMax = 0

output = image
wait_time = 33

while(1):

    # get current positions of all trackbars
    hMin = cv2.getTrackbarPos('HMin','image')
    sMin = cv2.getTrackbarPos('SMin','image')
    vMin = cv2.getTrackbarPos('VMin','image')

    hMax = cv2.getTrackbarPos('HMax','image')
    sMax = cv2.getTrackbarPos('SMax','image')
    vMax = cv2.getTrackbarPos('VMax','image')

    # Set minimum and max HSV values to display
    lower = np.array([hMin, sMin, vMin])
    upper = np.array([hMax, sMax, vMax])

    # Create HSV Image and threshold into a range.
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    mask = cv2.inRange(hsv, lower, upper)
    output = cv2.bitwise_and(image,image, mask= mask)

    # Print if there is a change in HSV value
    if( (phMin != hMin) | (psMin != sMin) | (pvMin != vMin) | (phMax != hMax) | (psMax != sMax) | (pvMax != vMax) ):
        print("(hMin = %d , sMin = %d, vMin = %d), (hMax = %d , sMax = %d, vMax = %d)" % (hMin , sMin , vMin, hMax, sMax , vMax))
        phMin = hMin
        psMin = sMin
        pvMin = vMin
        phMax = hMax
        psMax = sMax
        pvMax = vMax

    # Display output image
    cv2.imshow('image',output)

    # Wait longer to prevent freeze for videos.
    if cv2.waitKey(wait_time) & 0xFF == ord('q'):
        break

cv2.destroyAllWindows()

【讨论】:

  • 如何突出显示较小的补丁而不是较大的补丁?比如这样:user-images.githubusercontent.com/39755678/…
  • 使用具有最小/最大阈值区域的cv2.contourArea()。如果轮廓通过此过滤器,则突出显示它,否则忽略它。像maximum = 500if cv2.contourArea(c) &lt; maximum: 然后突出显示
猜你喜欢
  • 2021-04-11
  • 1970-01-01
  • 1970-01-01
  • 2015-12-18
  • 2021-06-24
  • 1970-01-01
  • 2013-07-17
  • 1970-01-01
  • 2020-06-26
相关资源
最近更新 更多