【问题标题】:Detect caps on bottles using opencv and python使用 opencv 和 python 检测瓶子上的盖子
【发布时间】:2014-08-15 17:45:47
【问题描述】:

我知道整个网络上有一百个关于我的问题的主题,但我想针对我的问题提出具体的问题,因为我尝试了几乎所有的解决方案,但都没有成功。

我正在尝试计算图像中的圆圈(是的,我已经尝试过霍夫圆圈,但由于光反射,我认为我的对象不是很健壮)。 然后我尝试创建一个分类器(没有成功我认为没有足够的特征所以检测不好)

我也尝试过 HSV 对话并尝试找到我的颜色对象(由于光线和颜色的变化,我再次遇到了一些问题) 正如您在图片上看到的,有 8 个大写字母,我希望能够数一数。

使用所有这些方法,我能够检测到图像上的对象(因为我正在优化特定图像的所有函数参数)但是一旦我加载了一个新的、相似的图像,结果令人失望.

请点击此链接查看Image

您可以在下面找到我尝试过的所有内容的一部分:

1.霍夫圆

img = cv2.imread('frame71.jpg',1)

img = cv2.medianBlur(img,5)
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
if img == None:
    print "There is no image file. Quiting..."
    quit()

circles = cv2.HoughCircles(img,cv.CV_HOUGH_GRADIENT,3,50,
                            param1=55,param2=125,minRadius=25,maxRadius=45)

circles = np.uint16(np.around(circles))
for i in circles[0,:]:
    # draw the outer circle
    cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
    # draw the center of the circle
    cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3)

print len(circles[0,:])
cv2.imshow('detected circles',cimg)
cv2.waitKey(0)
cv2.destroyAllWindows()

2。 HSV 变换、颜色检测

def image_process(frame, h_low, s_low, v_low, h_up, s_up, v_up, ksize):
  temp = ksize
  if(temp%2==1):
   ksize = temp
  else:
   ksize = temp+1
  #if(True):
  # return frame
  #thresh = frame
  #try:
  #TODO: optimize as much as possiblle this part of code
  try:
   hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
   lower = np.array([h_low, s_low, v_low],np.uint8)
   upper = np.array([h_up,s_up,h_up],np.uint8)
   mask = cv2.inRange(hsv, lower, upper)
   res = cv2.bitwise_and(hsv,hsv, mask= mask)
   thresh = cv2.cvtColor(res, cv2.COLOR_BGR2GRAY)
   #thresh = cv2.threshold(res, 50, 255, cv2.THRESH_BINARY)[1]
   thresh = cv2.threshold(thresh, 50, 255, cv2.THRESH_BINARY)[1]
   thresh = cv2.medianBlur(thresh,ksize)
  except Exception as inst:
    print type(inst)
   #cv2.imshow('thresh', thresh)
  return thresh

3.级联分类器

img = cv2.imread('frame405.jpg', 1)
cap_cascade = cv2.CascadeClassifier('haar_30_17_16_stage.xml')
caps = cap_cascade.detectMultiScale(img, 1.3, 5)
#print caps
for (x,y,w,h) in caps:
    cv2.rectangle(img, (x,y), (x+w,y+h), (255,0,0),2)


#cv2.rectangle(img, (10,10),(100,100),(0,255,255),4)

cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

quit()

关于训练分类器,我确实使用了很多不同的图像、样本、负例和正例、阶段数、w 和 h,但结果不是很准确。

最后,我想根据您的经验了解我应该遵循的最佳方法,我会坚持下去以优化我的检测。请记住,所有图像都是相似的,但并不完全相同。由于光线,运动等原因存在一些差异

比你提前,

【问题讨论】:

  • 您可以访问图像还是访问视频源?如果是视频,你应该能够通过瓶子的运动来分割瓶子,然后对提取的区域进行进一步的处理。
  • 瓶子的流量是恒定的,但我在凸轮下方的时候拍照。
  • 添加我尝试使用颜色查找帽子的那一刻,我认为问题在于帽子上方的透明尼龙。我用另一个图像测试我的代码,我能够隐藏图像中除颜色之外的所有其他内容,但是正如你在图像中看到的那样,我无法做到这一点。 HSV 的范围设置为最大值和最小值,但黄色被排除在外!图片:dl.dropboxusercontent.com/u/5502709/te.png
  • @user2117118 您找到了任何解决此问题的方法。我也面临同样的问题。

标签: opencv object colors geometry detection


【解决方案1】:

我对示例图像做了一些实验。我正在发布我的结果,如果您觉得它有用,您可以进一步改进和优化。步骤如下:

  • 对图像进行下采样
  • 进行形态学打开
  • 找到霍夫圆
  • 按半径对圆圈进行聚类(瓶子圆圈应获得相同的标签)
  • 按半径阈值过滤圆
  • 您还可以按中心 x 和 y 坐标对圆进行聚类(我还没有这样做)
  • 从过滤后的圆圈中准备一个蒙版并提取可能的瓶子区域
  • 按颜色对该区域进行聚类

代码是 C++。我正在附上我的结果。

    Mat im = imread(INPUT_FOLDER_PATH + string("frame71.jpg"));
    Mat small;
    int kernelSize = 9; // try with different kernel sizes. 5 onwards gives good results 

    pyrDown(im, small); // downsample the image

    Mat morph;
    Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(kernelSize, kernelSize));
    morphologyEx(small, morph, MORPH_OPEN, kernel); // open
    Mat gray;
    cvtColor(morph, gray, CV_BGR2GRAY);

    vector<Vec3f> circles;
    HoughCircles(gray, circles, CV_HOUGH_GRADIENT, 2, gray.rows/8.0);   // find circles

    // -------------------------------------------------------
    // cluster the circles by radii. similarly you can cluster them by center x and y for further filtering
    Mat circ = Mat(circles);
    Mat data[3];
    split(circ, data);

    Mat labels, centers;
    kmeans(data[2], 2, labels, TermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0), 2, KMEANS_PP_CENTERS, centers);
    // -------------------------------------------------------

    Mat rgb;
    small.copyTo(rgb);
    //cvtColor(gray, rgb, CV_GRAY2BGR);
    Mat mask = Mat::zeros(Size(gray.cols, gray.rows), CV_8U);

    for(size_t i = 0; i < circles.size(); i++)
    {
        Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
        int radius = cvRound(circles[i][2]);

        float r = centers.at<float>(labels.at<int>(i));
        if (r > 30.0f && r < 45.0f) // filter circles by radius (values are based on the sample image)
        {   
            // just for display
            circle(rgb, center, 3, Scalar(0,255,0), -1, 8, 0);
            circle(rgb, center, radius, Scalar(0,0,255), 3, 8, 0);
            // prepare a mask
            circle(mask, center, radius, Scalar(255,255,255), -1, 8, 0);
        }
    }

    // use each filtered circle as a mask and extract the region from original downsampled image
    Mat rgb2;
    small.copyTo(rgb2, mask);

    // cluster the masked region by color
    Mat rgb32fc3, lbl;
    rgb2.convertTo(rgb32fc3, CV_32FC3);
    int imsize[] = {rgb32fc3.rows, rgb32fc3.cols};
    Mat color = rgb32fc3.reshape(1, rgb32fc3.rows*rgb32fc3.cols);
    kmeans(color, 4, lbl, TermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0), 2, KMEANS_PP_CENTERS);
    Mat lbl2d = lbl.reshape(1, 2, imsize);
    Mat lbldisp;
    lbl2d.convertTo(lbldisp, CV_8U, 50);
    Mat lblColor;
    applyColorMap(lbldisp, lblColor, COLORMAP_JET);

结果:

过滤的圈子:

蒙面:

分段:

【讨论】:

  • 这看起来很有希望,我会尝试将这个和你的想法转化为我的程序,我会告诉你!
  • 请分享这个答案的python代码......
【解决方案2】:

你好,最后我想我找到了一种计算瓶子上盖的方法。

  1. 阅读图片
  2. 示教(查找 HSV 上限/下限的正确值)
  3. 选择想要的颜色(使用 HSV 和蒙版)
  4. 在蒙版图像上查找轮廓
  5. 找到轮廓的 minCircles
  6. 拒绝所有超出阈值的圈子

我还订购了一个偏光滤镜,我认为它可以大大减少眩光。我愿意接受进一步改进的建议(稳健性和速度)。健壮性和速度对我的应用程序来说都至关重要。

谢谢。

【讨论】:

    猜你喜欢
    • 2014-06-04
    • 1970-01-01
    • 2017-10-19
    • 2019-03-12
    • 2023-04-06
    • 2013-08-03
    • 2023-01-31
    • 2013-11-24
    • 2013-01-24
    相关资源
    最近更新 更多