首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >计算机视觉: Opencv计算大圆内的小圆

计算机视觉: Opencv计算大圆内的小圆
EN

Stack Overflow用户
提问于 2020-07-08 19:36:35
回答 3查看 401关注 0票数 0

这是我一直在处理的图像

目标是检测大圆圈中的小圆圈。

目前,我所做的是将图像转换为灰度并应用阈值(cv2.THRESH_OTSU),从而生成此图像

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

得到的图像如下所示

有没有人可以指导我做什么以及哪里错了。

下面是我一直在编写的附加代码

代码语言:javascript
复制
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()

谢谢!

EN

回答 3

Stack Overflow用户

发布于 2020-07-08 19:50:12

通过将图像转换为灰度,您可以丢弃许多有用的信息。

为什么不利用你正在寻找的斑点是唯一红色/橙色的这一事实呢?

我将饱和度通道与红色通道相乘,得到了以下图像:

现在,找到白色斑点变得微不足道了。

尝试对这些通道使用不同的权重,或首先应用阈值。有很多种方法。尝试不同的照明,不同的背景,直到你得到你的图像处理的理想输入。

票数 6
EN

Stack Overflow用户

发布于 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.

因此,可以使用以下简单代码来解决此问题。

代码语言:javascript
复制
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图像来分割橙色的点,然后用上面的方法检测它们。

代码语言:javascript
复制
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)

Resultant Image

票数 1
EN

Stack Overflow用户

发布于 2020-07-08 20:46:28

我有一个想法,通过滑动窗口来显示小圆圈。当小圆圈面积占滑动窗口面积大于90%(内接圆和正方形),小于100%(避免滑动窗口在大圆圈内移动)时。这个位置是一个小圆圈。最大滑动窗口大小是最大的小圆柱体大小。希望能有所帮助。

此外,根据Piglet的结果,应用k-means,其中k= 2,可以得到一个二值图像,然后使用findcontour来计算小圆圈。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62793937

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档