二维码检测

首先用形态学去膨胀整图,使二维码成为一个黑块,定位出这个正方形即获得二维码大致位置。 

二维码的三个角都有2个嵌套关系的矩形,以下根据轮廓嵌套关系去定位这3个点:

Mat imgSrc=imread("qrcode.jpg");
if(imgSrc.empty())
{
    cout<<"Load image error!!!"<<endl;
    return -1;
}
Mat imgGray,imgBin;
cvtColor(imgSrc,imgGray,COLOR_BGR2GRAY);
threshold(imgGray,imgBin,0,255,THRESH_BINARY_INV | THRESH_OTSU);
vector<vector<Point>> contours,contours2;
vector<Vec4i> hierarchy;
findContours(imgBin.clone(),contours,hierarchy,CV_RETR_TREE,CV_CHAIN_APPROX_NONE);
size_t nSize=contours.size();
int c=0,ic=0,area=0;
int parentIdx=-1;
for(size_t i=0;i<nSize;i++)
{
    if (hierarchy[i][2] != -1) //有子轮廓
    {
        if(ic==0) //TREE结构时,第一个父轮廓是最外层轮廓
            parentIdx = i;
        ic++;
    }
    else if(hierarchy[i][2] == -1)//无子轮廓
    {
        ic = 0;
        parentIdx = -1;
    }
    //找到定位点信息
    if ( ic >= 2) //有两层嵌套轮廓时
    {
        contours2.push_back(contours[parentIdx]); //添加父轮廓(最外层)
        ic = 0;
        parentIdx = -1;
    }
}
nSize=contours2.size();
if(nSize!=3) //是否找到的是3个轮廓
{
    cout<<"no codebar!!!"<<endl;
    return -1;
}
vector<Point2f> vecPts(3); //3个圆心坐标
for(size_t i=0;i<nSize;i++)
{
    //画轮廓,填充
    drawContours(imgSrc,contours2,i,Scalar(0,255,0),-1);
    //最小外接圆求圆心
    float radius;
    minEnclosingCircle(contours2[i],vecPts[i],radius);
    //circle(imgSrc,center,1,Scalar(0,0,255),2);
}
//圆心之间画线相连
for(size_t i=0;i<nSize;i++)
{
    int curId=i,nextId=(i+1)%3;
    line(imgSrc,vecPts[curId],vecPts[nextId],Scalar(0,0,255));
}

这里还可以根据轮廓长宽比(是否接近正方形)来删选轮廓,

还可以根据 "这三个点成直角三角形" 这一特性来提升准确性。

猜你喜欢

转载自blog.csdn.net/andylanzhiyong/article/details/89883537