python - Opencv将接触的圈子划分为单个

标签 python opencv

我有一张图片要处理。我需要检测图片中的所有圆圈。这是它。 org image

这是我的代码。

import cv2
import cv2.cv as cv
img = cv2.imread(imgpath)
cv2.imshow("imgorg",img)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow("gray",gray)
ret,thresh = cv2.threshold(gray, 199, 255, cv.CV_THRESH_BINARY_INV)
cv2.imshow("thresh",thresh)
cv2.waitKey(0)
cv2.destrotAllWindows()

然后,我得到了这样一张图片。 enter image description here

我尝试使用腐 eclipse 和扩张将它们分成单个。但它不起作用。我的问题是如何将这些接触的圆圈分成单个,以便我可以检测到它们。

根据@Micka的想法,我尝试按照以下方式处理图像,这是我的代码。

import cv2
import cv2.cv as cv
import numpy as np

def findcircles(img,contours):
    minArea = 300;
    minCircleRatio = 0.5;
    for  contour  in contours:

        area = cv2.contourArea(contour)
        if area < minArea: 
            continue

        (x,y),radius = cv2.minEnclosingCircle(contour)
        center = (int(x),int(y))
        radius = int(radius)
        circleArea = radius*radius*cv.CV_PI;

        if area/circleArea < minCircleRatio:
             continue;
        cv2.circle(img, center, radius, (0, 255, 0), 2)
        cv2.imshow("imggg",img)

img = cv2.imread("a.png")
cv2.imshow("org",img)

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,threshold = cv2.threshold(gray, 199, 255,cv. CV_THRESH_BINARY_INV)
cv2.imshow("threshold",threshold)

blur = cv2.medianBlur(gray,5)
cv2.imshow("blur",blur)

laplacian=cv2.Laplacian(blur,-1,ksize = 5,delta = -50)
cv2.imshow("laplacian",laplacian)

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(7,7))
dilation = cv2.dilate(laplacian,kernel,iterations = 1)
cv2.imshow("dilation", dilation)

result= cv2.subtract(threshold,dilation) 
cv2.imshow("result",result)

contours, hierarchy = cv2.findContours(result,cv2.RETR_LIST,cv2.CHAIN_APPROX_NONE)
findcircles(gray,contours)

但我没有得到与@Micka 相同的效果。我不知道哪一步是错误的。

最佳答案

适应@jochen 的想法我得出了这个:

  1. 像你所做的那样提取完整的圆形 mask (我称之为 fullForeground )

enter image description here

  1. 从您的彩色图像计算灰度,对其进行模糊处理(中值模糊大小为 7)并提取边缘,例如使用 cv::Laplacian 这个 laplacian thresholded > 50 给出:

cv::Laplacian(blurred, lap, 0, 5);//没有增量 lapMask = 圈 > 50;//阈值 > 50

enter image description here

这个扩大一次给出:

cv::dilate(lapMask, dilatedThresholdedLaplacian, cv::Mat()); // dilate the edge mask once

enter image description here

现在减法 fullForeground - dilatedThresholdedLaplacian(与此类掩码的 and_not 运算符相同)给出:

enter image description here

由此您可以计算轮廓。对于每个轮廓,您可以计算面积并将其与封闭圆的面积进行比较,给出以下代码和结果:

std::vector<std::vector<cv::Point> > contours;
cv::findContours(separated.clone(), contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);

double minArea = 500;
double minCircleRatio = 0.5;
for(unsigned int i=0; i<contours.size(); ++i)
{
    double cArea = cv::contourArea(contours[i]);
    if(cArea < minArea) continue;

    //filteredContours.push_back(contours[i]);
    //cv::drawContours(input, contours, i, cv::Scalar(0,255,0), 1);
    cv::Point2f center;
    float radius;
    cv::minEnclosingCircle(contours[i], center, radius);

    double circleArea = radius*radius*CV_PI;

    if(cArea/circleArea < minCircleRatio) continue;

    cv::circle(input, center, radius, cv::Scalar(0,0,255),2);
}

enter image description here

这是显示覆盖范围的另一张图片:

enter image description here

希望对你有帮助

关于python - Opencv将接触的圈子划分为单个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34650697/

相关文章:

python - setup_method 中的 py.test session 级固定装置

python - numpy 浮点错误 : invalid value encountered in subtract - not reproducible?

opencv - 凸轮移位闭塞

python - 检查字符串是否包含子字符串或其中的一部分

python - 多标签数据的计数图

c++ - OpenCV - SURF 特征比较

python - Python/OpenCV网络摄像头向后移动

c++ - 如何在 opencv 和 c++ 中使用鼠标在图像上画线?

c++ - C++ 中的多线程应用程序和 OpenCV?

python - 如何获取从 django.template 导入的 RequestContext 字典