当形状未闭合时从二进制图像中检测圆形和椭圆

Posted

技术标签:

【中文标题】当形状未闭合时从二进制图像中检测圆形和椭圆【英文标题】:Detect circles and ellipses from binary image when the shapes are not closed 【发布时间】:2021-11-18 08:47:49 【问题描述】:

我尝试在 RGB 图像中检测葡萄串(通常具有圆形和椭圆形)中的葡萄浆果。 我的数据集的几个例子:

我不关心检测所有浆果,但我确实希望检测到的浆果尽可能准确。检测图像中大约 30%-40% 的浆果就足够了。

到目前为止,我设法达到了这个阶段,您可以更清楚地看到葡萄串和一些浆果的边界

我是通过以下步骤完成的:

    将图像转换为灰度 高斯滤波器 canny 算法,使用 THRESH_OTSU 方法 cv2.connectedComponentsWithStats 减少点和细线 形态扩张使线条变粗

我正在寻找一种方法来将图像中的浆果检测为形状,以便以后从中提取指标,例如半径、面积、长度等。我想到了看起来与我非常相似的圆形和椭圆形,但是我当然愿意接受其他想法。

显然也欢迎使用与我使用的不同预处理阶段的解决方案!

我用来生成这个的代码:

import cv2 as cv
import numpy as np


def connected_dots(binary_map):
    # do connected components processing
    nlabels, labels, stats, centroids = cv.connectedComponentsWithStats(binary_map, None, None, None, 8, cv.CV_32S)

    # get CC_STAT_AREA component as stats[label, COLUMN]
    areas = stats[1:, cv.CC_STAT_AREA]
    result = np.zeros((labels.shape), np.uint8)
    for i in range(0, nlabels - 1):
        if areas[i] >= 30:  # keep
            result[labels == i + 1] = 255
    result = cv.dilate(result, kernel=np.ones((2, 2), np.uint8), iterations=1)  # make the lines thicker
    return result


# load the masked image containing only the grape bunch
img_rgb = cv.imread("grape.jpg")
img_rgb = cv.cvtColor(img_rgb, cv.COLOR_BGR2RGB)
grayscale = cv.cvtColor(img_rgb, cv.COLOR_RGB2GRAY)  # convert to grayscale
threshValue = 140
_, binaryImage = cv.threshold(grayscale, threshValue, 255, cv.THRESH_TOZERO_INV)  # remove white areas

kernel_size = 3
gaussian_blurred = cv.GaussianBlur(binaryImage, (kernel_size, kernel_size), 0)
binaryImage = gaussian_blurred
th, bw = cv.threshold(binaryImage, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)  # calc threshold for canny
edges = cv.Canny(binaryImage, th / 2, th)
edges = connected_dots(edges)

编辑 1

@Abhi25t 建议的灰度图像直方图

编辑 2

按照@Micka 的建议使用 cv2.equalizeHist 函数后,我得到了看起来更好的结果(再次,我关心的是准确检测一些葡萄)。仍在寻找检测葡萄浆果的好方法(看起来像椭球体)

【问题讨论】:

在你的位置上,我会看到更好的照片(也有更好的照明)。这些图片分辨率低、模糊、几乎没有对比度 我希望我能做到!不幸的是,这是我必须使用的数据集。 我认为 Hough circles 会找到不完整的圆。然而,这些物体实际上是椭球体。查看[this question],它有一个使用scikit库的解决方案 将它们转换为灰度并扩展直方图以增加对比度。那么其他算法比如 otsu 会更好地工作 cv2.equalizeHist 函数 【参考方案1】:

我会做的是

    使用阈值检测黑色像素(例如,otsu,或者使用大多数图像是黑色的事实,因此黑色像素应该在中值颜色 +- 5% 左右,并且具有大致相同的 r、g 和 b值) 使用 canny-edge 检测边缘,并抑制靠近黑色部分的边缘 对结果应用椭圆霍夫变换,并在距离上有足够的阈值

注意:您可能想要简单地缩小图像的比例,而不是使用扩张来扩大边界,这也将加快计算速度。

【讨论】:

以上是关于当形状未闭合时从二进制图像中检测圆形和椭圆的主要内容,如果未能解决你的问题,请参考以下文章

如何在matlab中实现灰度形态检测灰度图像上的圆形物体?

UIView contentstretch 将圆形更改为椭圆形,而不是药丸形状

从二进制获取图像尺寸和图像大小

从二进制图像OpenCV C++中裁剪文本

使用python从二进制图像中裁剪感兴趣区域

如何使用xml中的可绘制形状绘制半椭圆形(Android)