Opencv 检测瓶子是否有标签

Opencv 检测瓶子是否有标签,opencv,computer-vision,Opencv,Computer Vision,我目前正在用openCv做一点计算机视觉。我有一个瓶子的样品,上面有标签。我试图确定瓶子什么时候没有标签。 标签是长方形的 我使用Canny进行了边缘检测。我尝试使用findcountour()来检测瓶子是否有内部轮廓(这将代表矩形标签)。我猜只要看看瓶子上是否有文本就足够了(如果有,则它有标签,反之亦然)。。你可以查看一个项目,如。。这方面的论文很多;其中一些比较著名的作品是由斯坦福大学简历组完成的,而且 HTH如果你的问题就这么简单,只需用一个矩形来缩小你的图像 cv::Mat image

我目前正在用openCv做一点计算机视觉。我有一个瓶子的样品,上面有标签。我试图确定瓶子什么时候没有标签。 标签是长方形的


我使用Canny进行了边缘检测。我尝试使用findcountour()来检测瓶子是否有内部轮廓(这将代表矩形标签)。

我猜只要看看瓶子上是否有文本就足够了(如果有,则它有标签,反之亦然)。。你可以查看一个项目,如。。这方面的论文很多;其中一些比较著名的作品是由斯坦福大学简历组完成的,而且


HTH

如果你的问题就这么简单,只需用一个矩形来缩小你的图像

cv::Mat image = imread("image.png");
cv::Rect labelRegion(50, 200, 50, 50);
cv::Mat labelImage = image(labelRegion);
然后将图像区域分解为三个通道

cv::Mat channels[3];
cv::split(labelImage, channels);

cv::Mat labelImageRed = channels[2];
cv::Mat labelImageGreen = channels[1];
cv::Mat labelImageBlue = channels[0];
然后对每个单通道图像设置阈值,并计算零/非零像素数

I'm not providing code for this part!
如果图像上没有标签,则每个通道的值都大于~200(您应该对此进行检查)。如果有标签,那么在计算零/非零像素与未标签像素的数量时,您将看到不同的结果。

\include
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;
int main()
{

    Mat img=imread("c:/data/bottles/1.png");
    Mat gray;
    cvtColor(img,gray,CV_BGR2GRAY);
    resize(gray,gray,Size(50,100));
    Sobel(gray,gray,CV_16SC1,0,1);
    convertScaleAbs(gray,gray);
    if(sum(gray)[0]<130000)
    {       
        cout<<"no label";
    }else{
        cout<<"has label";
    }
    imshow("gray",gray);
    waitKey();
    return 0;
}
使用名称空间cv; 使用名称空间std; int main() { Mat img=imread(“c:/data/瓶/1.png”); 席灰色; CVT颜色(img、灰色、CV_bgr2灰色); 调整大小(灰色、灰色、大小(50100)); Sobel(灰色,灰色,CV_16SC1,0,1); 可转换比例(灰色、灰色);
如果(sum(gray)[0]guneykayim建议使用图像分割,我觉得这是最简单的方法。我只是增加了一点

我的建议是,您将BGR图像转换为YCbCr,然后在Cb和Cr通道中查找与标签颜色匹配的值。这将允许您轻松地分割颜色,即使瓶子上的照明条件发生变化(暗光瓶子的白色区域最终会呈现深灰色,如果您有灰色标签,这可能是一个问题)

类似的内容在python中应该可以工作:

# Required moduls
import cv2
import numpy

# Convert image to YCrCb
imageYCrCb = cv2.cvtColor(sourceImage,cv2.COLOR_BGR2YCR_CB)

# Constants for finding range of label color in YCrCb
# a, b, c and d need to be defined
min_YCrCb = numpy.array([0,a,b],numpy.uint8) 
max_YCrCb = numpy.array([0,c,d],numpy.uint8)

# Threshold the image to produce blobs that indicate the labeling
labelRegion = cv2.inRange(imageYCrCb,min_YCrCb,max_YCrCb)

# Just in case you are interested in going an extra step
contours, hierarchy = cv2.findContours(labelRegion, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# Draw the contour on the source image
for i, c in enumerate(contours):
    area = cv2.contourArea(c)
    if area > minArea: # minArea needs to be defined, try 300 square pixels
        cv2.drawContours(sourceImage, contours, i, (0, 255, 0), 3)
如果您决定使用BGR图像,函数cv2.inRange()也将起作用

参考资料:


您能提供一些详细信息吗?例如,到目前为止您尝试了什么,示例图像等?@scap3y我已经使用Canny进行了边缘检测。我正在尝试使用findcountour()检测瓶子是否有内部轮廓(这将代表标签).看看这个:…这个问题和你的非常相似,希望他们已经用Mathematica解决了(不过,代码可以很容易地移植到OpenCV。。HTH@scap3y谢谢。我需要更简单的东西,因为我想从头开始学习。我仍然不确定你到底需要什么。请你具体点好吗?我已经给了你问题的解决方案。我认为这个解决方案太过分了,我们首先需要看更多的图片s、 。可能不是所有标签上都有文字。我认为这将提供最可靠的解决方案(针对不同的瓶形+颜色)…也许吧,但正如杰克解释的那样,这是解决这个问题的一个复杂的解决方案…你从哪里得到130000的值?猜测…从没有标签的瓶子。它可以更高,因为有标签的瓶子和没有标签的瓶子之间有很大的差距。这是基于标签产生更多边缘的观察吗(不管标签上是否有文字)并且图像方向大致固定,因此实际上可以直接比较边缘大小之和。通常对于sobel,x和y导数是平方的,求和,然后平方衰减(实际上是得到abs值).但在这里,仅仅做y是更好和足够的(基于图像).但是sobel响应中有正值和负值,所以我们不能简单地求和,因为它们会相互抵消。convertscaleabs会为您这样做。优化是必要的,以确保梯度大小具有可比性。130000的选择非常随意,我不能说这种方法适用于所有的图像,因为我没有看到所有的图像但是我可以非常自信地说(如果你所有的图片都与你给出的非常相似的话)如果你计算所有图像的这个值,应该可以找到一个完全分开标签图像和非标签图像的数字。你可以只对图像的下半部分这样做,因为对于非标签瓶子,它几乎不会产生响应。另一种解释是,这种方法与o做canny edge,然后计算白色像素的数量。像素越多,成为标签瓶的可能性就越大。但是它比canny的步骤要少edge@guneykayim谢谢。我会尝试一下,只是这种方法容易受到光照条件的影响,瓶子上的阴影可能会被算法误认为标签。耶哟你是对的,这就是为什么我要求从样本图像,但他没有再提供:)我认为这个解决方案对这些图像是足够的。这是一个好的解决方案,使用边缘检测将对噪声更加敏感。如果你想要更复杂的东西,你可以使用颜色直方图和建立一个用于分类的训练数据集。