python - 使用 OpenCV 计算蚕卵

标签 python opencv computer-vision

我正在尝试编写一个 python 脚本来计算蚕卵的数量。有些图像真的很小,有些有重叠的椭圆/圆圈,这使得它有点困难。我尝试了以下方法:

im = cv2.imread('eggs1.png')
hsv = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
th, bw = cv2.threshold(hsv[:, :, 2], 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
morph = cv2.morphologyEx(bw, cv2.MORPH_CLOSE, kernel)
dist = cv2.distanceTransform(morph, cv2.DIST_L2, cv2.DIST_MASK_PRECISE)
borderSize = 75
distborder = cv2.copyMakeBorder(dist, borderSize, borderSize, borderSize, borderSize, 
                                cv2.BORDER_CONSTANT | cv2.BORDER_ISOLATED, 0)
gap = 10                                
kernel2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2*(borderSize-gap)+1, 2*(borderSize-gap)+1))
kernel2 = cv2.copyMakeBorder(kernel2, gap, gap, gap, gap, 
                                cv2.BORDER_CONSTANT | cv2.BORDER_ISOLATED, 0)
distTempl = cv2.distanceTransform(kernel2, cv2.DIST_L2, cv2.DIST_MASK_PRECISE)
nxcor = cv2.matchTemplate(distborder, distTempl, cv2.TM_CCOEFF_NORMED)
mn, mx, _, _ = cv2.minMaxLoc(nxcor)
th, peaks = cv2.threshold(nxcor, mx*0.5, 255, cv2.THRESH_BINARY)
peaks8u = cv2.convertScaleAbs(peaks)
contours, hierarchy = cv2.findContours(peaks8u, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
peaks8u = cv2.convertScaleAbs(peaks)    # to use as mask
for i in range(len(contours)):
    x, y, w, h = cv2.boundingRect(contours[i])
    _, mx, _, mxloc = cv2.minMaxLoc(dist[y:y+h, x:x+w], peaks8u[y:y+h, x:x+w])
    cv2.circle(im, (int(mxloc[0]+x), int(mxloc[1]+y)), int(mx), (255, 0, 0), 2)
    cv2.rectangle(im, (x, y), (x+w, y+h), (0, 255, 255), 2)
    cv2.drawContours(im, contours, i, (0, 0, 255), 2)

cv2.imshow('circles', im)
cv2.waitKey(0)
cv2.destroyAllWindows()
gray = cv2.imread("eggs2.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("Dots number: {}".format(len(xcnts)))

import cv2
import numpy as np

img = cv2.imread('image4.jpg', 0)
seed_pt = (184,252)
fill_color = 50
mask = np.zeros_like(img)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
for th in range(60, 120):
    prev_mask = mask.copy()
    mask = cv2.threshold(img, th, 255, cv2.THRESH_BINARY)[1]
    mask = cv2.floodFill(mask, None, seed_pt, fill_color)[1]
    mask = cv2.bitwise_or(mask, prev_mask)
    mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
cv2.imshow('image',mask)
cv2.waitKey(0)
cv2.destroyAllWindows()

countour 的发现是最接近的,但在像 this one 这样的图像时失败了被使用。其中一些图片包括:1 , 2

是否有更好的方法来获得准确或接近准确的计数?

最佳答案

正如这里的人(Cris Luengo、Micka 和 rayryeng)所说,第一张图片很难处理。但是,我看到了一种解决方法(不确定它是否有效,但希望如此)。

鸡蛋可能有不同的颜色,因此使用 HSV/RGB 阈值可能并不总是有效,或者总是需要调整。我建议尝试使用边缘检测算法。具体来说,看看 Laplacian、Canny 和 Sobel 方法。

基本上,这些方法会寻找图像颜色的剧烈变化。让我们考虑 Sobel 算子,它通过各个掩码的卷积和沿图像的滑动窗口来工作。该卷积给出了区域的数值微分,因此颜色变化越多,运算符的输出就越多。如果需要,您可以对其进行阈值处理以获得二值图像。

Example of Sobel operator on Lena

有了二进制图像,您可以使用它的形态来减少噪声并提高图像质量。如果效果好,可以得到鸡蛋的闭合轮廓,或多或少是可数的。

这种方法当然可以归结为与 HSV/RGB 阈值处理类似的方法,但在计算重叠鸡蛋时可能很有用。

如果您有大量(实际上是大量)时间和数据需要处理,您可能需要使用机器学习(HOG+SVM、RCNN 等)。但这需要大量的数据和时间来完成。

祝你好运!

关于python - 使用 OpenCV 计算蚕卵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56511177/

相关文章:

python - 使用 GTK 时保持后台事件处于事件状态

python - Python中使用正则表达式进行批量替换

python - python关于openingRect的opencv错误

algorithm - 检测(很可能)不是照片的统一图像

python - 对数据框列中的值进行自定义过滤器 (Python)

python - 在哪里可以找到 _sre.py python 内置模块?

c++ - 通过 OpenCV/C++ 使用 Android 手机摄像头作为网络摄像头

opencv - 矩形数组OpenCv中的交点

python - 如何通过 OpenCV 验证标记的特征是否正确跟踪视频中的对象?

c++ - 单 channel 平均值