这是我一直在处理的图像

目标是检测大圆圈中的小圆圈。
目前,我所做的是将图像转换为灰度并应用阈值(cv2.THRESH_OTSU),从而生成此图像

在这之后,我使用findcontour过滤出大对象,使用我在stackoverflow上找到的椭圆形内核应用Morph open
得到的图像如下所示

有没有人可以指导我做什么以及哪里错了。
下面是我一直在编写的附加代码
import cv2
import numpy as np
# Load image, grayscale, Otsu's threshold
image = cv2.imread('01.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
#cv2.imwrite('thresh.jpg', thresh)
# Filter out large non-connecting objects
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
area = cv2.contourArea(c)
#print(area)
if area < 200 and area > 0:
cv2.drawContours(thresh,[c],0,0,-1)
# Morph open using elliptical shaped kernel
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=3)
# Find circles
cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
area = cv2.contourArea(c)
if area > 20 and area < 50:
((x, y), r) = cv2.minEnclosingCircle(c)
cv2.circle(image, (int(x), int(y)), int(r), (36, 255, 12), 2)
cv2.namedWindow('orig', cv2.WINDOW_NORMAL)
cv2.imshow('orig', thresh)
cv2.namedWindow('image', cv2.WINDOW_NORMAL)
cv2.imshow('image', image)
cv2.waitKey()谢谢!
发布于 2020-07-08 19:50:12
通过将图像转换为灰度,您可以丢弃许多有用的信息。
为什么不利用你正在寻找的斑点是唯一红色/橙色的这一事实呢?
我将饱和度通道与红色通道相乘,得到了以下图像:

现在,找到白色斑点变得微不足道了。
尝试对这些通道使用不同的权重,或首先应用阈值。有很多种方法。尝试不同的照明,不同的背景,直到你得到你的图像处理的理想输入。
发布于 2020-07-08 21:43:01
代码中的主要问题是在cv2.findContours.()函数中使用的标志。
对于这样的问题,我们必须找到可能出现在另一个轮廓(大圆)中的轮廓,我们不应该使用标志cv2.RETR_EXTERNAL,而应该使用cv2.RETR_TREE。Click here for detailed info.。
此外,如果内存不是问题,使用cv2.CHAIN_APPROX_NONE总是比使用cv2.CHAIN_APPROX_SIMPLE更好。Click here for detailed info.
因此,可以使用以下简单代码来解决此问题。
import cv2
import numpy as np
Image = cv2.imread("Adg5.jpg")
GrayImage = cv2.cvtColor(Image, cv2.COLOR_BGR2GRAY)
# Applying Otsu's Thresholding
Retval, ThreshImage = cv2.threshold(GrayImage, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
# Finding Contours in the image
Contours, Hierarchy = cv2.findContours(ThreshImage, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# Taking only those contours which have no child contour.
FinalContours = [Contours[i] for i in range(len(Contours)) if Hierarchy[0][i][2] == -1]
# Drawing contours
Image = cv2.drawContours(Image, FinalContours, -1, (0, 255, 0), 1)
cv2.imshow("Contours", Image)
cv2.waitKey(0)Resulting image在这种方法中,边界上也会有很多噪声,但也会检测到所需的橙色点。现在的任务是去除边界噪声。
另一种在很大程度上消除边界噪声的方法类似于@Piglet的方法,在这里,我使用HSV图像来分割橙色的点,然后用上面的方法检测它们。
import cv2
import numpy as np
Image = cv2.imread("Adg5.jpg")
HSV_Image = cv2.cvtColor(Image, cv2.COLOR_BGR2HSV)
# Extracting orange colour using HSV Image.
ThreshImage = cv2.inRange(HSV_Image, np.array([0, 81, 0]), np.array([41, 255, 255]))
# Finding Contours
Contours, Hierarchy = cv2.findContours(ThreshImage, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# Taking only those contours which have no child contour.
FinalContours = [Contours[i] for i in range(len(Contours)) if Hierarchy[0][i][2] == -1]
# Drawing Contours
Image = cv2.drawContours(Image, FinalContours, -1, (0, 255, 0), 1)
cv2.imshow("Contours", Image)
cv2.waitKey(0)发布于 2020-07-08 20:46:28
我有一个想法,通过滑动窗口来显示小圆圈。当小圆圈面积占滑动窗口面积大于90%(内接圆和正方形),小于100%(避免滑动窗口在大圆圈内移动)时。这个位置是一个小圆圈。最大滑动窗口大小是最大的小圆柱体大小。希望能有所帮助。
此外,根据Piglet的结果,应用k-means,其中k= 2,可以得到一个二值图像,然后使用findcontour来计算小圆圈。
https://stackoverflow.com/questions/62793937
复制相似问题