天天看點

瓶口缺陷檢測

摘要

本文使用opencv實作Halcon中的一個瓶口缺陷檢測執行個體(C++實作),Halcon中對應的例子為inspect_bottle_mouth.hdev,用于檢測酒瓶瓶口是否出現破損等缺陷情形。

 Halcon執行個體主要步驟包含五步,分别是:

  • 使用門檻值處理和形态學粗定位品口位置;
  • XLD輪廓拟合最近似的圓形區域作為瓶口的輪廓;
  • 極坐标變換,轉換到水準或垂直方向進行處理;
  • 均值濾波圖與原圖做差分,根據門檻值提取;
  • 将繪制的缺陷部分通過反極坐标變換投影到原圖上。

需要注意的是:在opencv中第一步和第二步這裡直接用霍夫圓變換來替換(最重要的就是參數要設定合适)。

opencv實作步驟分解:

 (一)讀入圖像,預處理,霍夫圓檢測

Mat dst,src1;
    Mat src = imread("D:/opencv練習圖檔/瓶口缺陷檢測.png");
    src.copyTo(src1);
    imshow("原圖", src);
    //預處理,霍夫園檢測
    Mat gray;
    cvtColor(src, gray, COLOR_RGB2GRAY);
    medianBlur(gray, gray, 3);
    vector<Vec3f>circles;
    HoughCircles(gray, circles, HOUGH_GRADIENT, 1, 100, 200, 30, 150, 500);      
瓶口缺陷檢測

 我測試了一下,16張測試圖,效果都不錯,暫時采用它。但是對于霍夫圓檢測,設定參數必須精确,才能有效果。

  • HoughCircles函數API
vector<Vec3f>circles;
HoughCircles(gray, circles, HOUGH_GRADIENT, 1, 100, 200, 30, 150, 500);
//第一個參數是輸出被檢測圖檔
//第二個參數表示存儲數組,其中存儲被檢測的圓的圓心的坐标和圓的半徑。
//第三個參數是檢測圓的方法(霍夫梯度法)
//第四個參數可以設定為1就行--預設參數
//第五個參數是圓心與圓心之間的距離,這是一個經驗值。這個大了,那麼多個圓就是被認為一個圓。
//第六個參數 就設為預設值就OK
//第七個參數這個根據你的圖像中的圓  大小設定,如果圓越小,則設定越小
//第八個和第九個參數 是你檢測圓 最小半徑和最大半徑是多少  這個是經驗值      

 (二)極坐标變換(重點就是要準确找到圓心作為極坐标變換的中心)

int X = 0;//圓心坐标的X
    int Y = 0;//圓心坐标的Y
    int R = 0;//半徑
    Mat ROI;
    for (int i = 0; i < circles.size(); i++)
    {
         X = cvRound(circles[i][0]);
        Y = cvRound(circles[i][1]);
        Point center(X,Y);//圓心坐标
         R = cvRound(circles[i][2]);
         ROI = src(Rect(X - R, Y - R, 2 * R, 2 * R));//提取ROI區域
         Point trans_center = Point(R, R);//ROI區域内的中心坐标
        warpPolar(ROI, dst, Size(300, 600), trans_center, R, INTER_LINEAR | WARP_POLAR_LINEAR);

    }
    imshow("ROI區域", ROI);
    imshow("極坐标變換", dst);      
瓶口缺陷檢測
瓶口缺陷檢測

 (三)均值濾波做差分,二值化

//均值濾波做差分
    Mat dst_blur,diff,binary,dst_gray;
    cvtColor(dst, dst_gray, COLOR_RGB2GRAY);
    blur(dst_gray, dst_blur, Size(3, 501), Point(-1, -1));
    absdiff(dst_gray, dst_blur, diff);
    imshow("差分", diff);
    threshold(diff, binary, 70, 255, THRESH_BINARY);
    medianBlur(binary, binary, 3);
    imshow("二值化", binary);      
瓶口缺陷檢測
瓶口缺陷檢測

 注意這裡的均值濾波核大小,一般我們都是設定(3,3)或(5,5)等,這裡物體垂直方向較長,參考Halcon例子中設定為(3, 501)。

可以看到,通過均值濾波差分後圖像的缺陷已經可以很明顯的看到了。

 (四)輪廓提取,篩選缺陷輪廓

vector<vector<Point>>contours;
    findContours(binary, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point());
    for (int i = 0; i < contours.size(); i++)
    {
        Rect rect = boundingRect(contours[i]);
        float width = rect.width;
        if (width>10)
        {
            drawContours(dst, contours,i, Scalar(0, 0, 255), 2);
        }
    }
    imshow("缺陷", dst);      
瓶口缺陷檢測

 這裡篩選缺陷的标準是:輪廓寬度大于10的都認為是缺陷(可以添加更精确的标準)

(五)反極坐标變換,結果投影到原圖

Mat polarImg_Inv;
    warpPolar(dst, polarImg_Inv, ROI.size(), Point(R,R), R, INTER_LINEAR | WARP_POLAR_LINEAR| WARP_INVERSE_MAP);
    circle(polarImg_Inv, Point(R, R), 3, Scalar(0, 255, 0), -1, 8, 0);
    circle(polarImg_Inv, Point(R, R), R, Scalar(255, 0, 0), 3, 8, 0);
    imshow("反極坐标變換", polarImg_Inv);      
瓶口缺陷檢測