Home > Net >  OpenCV detect which pins are bent
OpenCV detect which pins are bent

Time:10-13

I have this image of a pin header, and I need to detect if there are bent pins in the header using OpenCV.

What is the best way to do this!? I have made the following so far. But I'm not sure if this is the correct way of doing it.

I use Canny edge detection and then HoughLinesP to check for lines.

for (const auto &entry: fs::directory_iterator(SAMPLES)) {
    try {
        // Load src image
        src = imread(entry.path(), IMREAD_COLOR);
        cvtColor(src, gray, COLOR_BGR2GRAY);
//            blur(gray, blurMat, Size(3, 3));
        cropped = gray(Range(150,230), Range(0, gray.cols));

        // Edge detection
        Canny(cropped, detected_edges, thres1, thres2, 3);
        imshow("cropped", cropped);
        imshow("src", src);
        imshow("detected_edges", detected_edges);

        // Probabilistic Line Transform
        vector<Vec4i> linesP; // will hold the results of the detection
        HoughLinesP(detected_edges, linesP, 1, CV_PI/180, 20, 50, 10 ); // runs the actual detection
        // Draw the lines
        for( size_t i = 0; i < linesP.size(); i   )
        {
            Vec4i l = linesP[i];
            line( src, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, LINE_AA);
        }

        imshow(entry.path().filename(), src);
        waitKey();

    } catch (const std::exception &e) {
        cout << e.what() << endl;
    }
}

The output looks like this then:

So in theory I only have to check if the angle of a line is greater than some threshold. But Maybe I got it all wrong. I like to hear from you.

CodePudding user response:

Have a look at cv::findContours.

You should be able to extract the pins with that, maybe binarize first with cv::threshold(). Then using center-of-mass and the moment-of-area for the contours found, you can describe the position and angle of the pins. Or just using the bounding rectangle might even be enough.

CodePudding user response:

Here is my approach with code and results.

Steps to produce:

(preprocessing)

  1. Apply median to decrease noise in the image
  2. Apply threshold to get a clear image

Here is the result of these 2 steps:

(there is a server error but i will add image later)

  1. Check each row and get the sticks according to the thickness threshold.

Result image of this step:

(there is a server error but i will add image later)

  1. Get mid point's y axis values of each stick and hold in an array.
  2. Calculate the standard deviation of each array and choose the ones which are higher.

Here is the code:

#include <string>
#include <opencv2/opencv.hpp>
#include <opencv2/dnn_superres.hpp>
#include <numeric>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/mean.hpp>
#include <boost/accumulators/statistics/moment.hpp>
using namespace boost::accumulators;
using namespace std;
using namespace boost;

double stddev(std::vector<int> const & func)
{
    double mean = std::accumulate(func.begin(), func.end(), 0.0) / func.size();
    double sq_sum = std::inner_product(func.begin(), func.end(), func.begin(), 0.0,
        [](double const & x, double const & y) { return x   y; },
        [mean](double const & x, double const & y) { return (x - mean)*(y - mean); });
    return std::sqrt(sq_sum / func.size());
}


int main(){

    cv::Mat img = cv::imread("/home/yns/Downloads/aaa.jpg",cv::IMREAD_GRAYSCALE);

    cv::namedWindow("input",0);
    cv::namedWindow("output",0);
    cv::namedWindow("output2",0);

    cv::imshow("input",img);


    cv::Mat out;

    cv::medianBlur(img,img,3);

    cv::threshold(img,out,80,255,cv::THRESH_BINARY);

    cv::Mat out2;

    cv::cvtColor(out,out2,cv::COLOR_GRAY2BGR);


    cv::imshow("output",out);

    int start = 0;
    int cnt = 0;
    int refX = 0;
    int thresholdThickness = 5;

    int orderNum = 1;

    std::vector<int> yAxis_1;
    std::vector<int> yAxis_2;
    std::vector<int> yAxis_3;
    std::vector<int> yAxis_4;
    std::vector<int> yAxis_5;
    std::vector<int> yAxis_6;
    std::vector<int> yAxis_7;
    std::vector<int> yAxis_8;
    std::vector<int> yAxis_9;
    std::vector<int> yAxis_10;
    std::vector<int> yAxis_11;
    std::vector<int> yAxis_12;


    int annen = 0;

    for(int i=0; i<out.rows; i  )
    {
        orderNum = 1;
        annen = 0;
        for(int j=0; j<out.cols; j  )
        {

            if(out.at<uchar>(cv::Point(j,i))==255 && start != 1)
            {
                start = 1;
                refX = j;
                cnt = 0;
            }
            else if (out.at<uchar>(cv::Point(j,i))==255)
            {
                cnt  ;
            }
            else if (out.at<uchar>(cv::Point(j,i))==0 && start == 1 && cnt>thresholdThickness) {
                cv::circle(out2,cv::Point((j refX)/2,i),1,cv::Scalar(0,0,255),cv::FILLED);
                start = 0;
                annen  ;
                if(orderNum == 1)
                    yAxis_1.push_back(j);
                if(orderNum == 2)
                    yAxis_2.push_back(j);
                if(orderNum == 3)
                    yAxis_3.push_back(j);
                if(orderNum == 4)
                    yAxis_4.push_back(j);
                if(orderNum == 5)
                    yAxis_5.push_back(j);
                if(orderNum == 6)
                    yAxis_6.push_back(j);
                if(orderNum == 7)
                    yAxis_7.push_back(j);
                if(orderNum == 8)
                    yAxis_8.push_back(j);
                if(orderNum == 9)
                    yAxis_9.push_back(j);
                if(orderNum == 10)
                    yAxis_10.push_back(j);
                if(orderNum == 11)
                    yAxis_11.push_back(j);
                if(orderNum == 12)
                    yAxis_12.push_back(j);

                orderNum  ;

            }
            else if (out.at<uchar>(cv::Point(j,i))==0 && start == 1)
            {
                start = 0;
            }
        }

    }

    std::cout<<stddev(yAxis_1)<<std::endl;
    std::cout<<stddev(yAxis_2)<<std::endl;
    std::cout<<stddev(yAxis_3)<<std::endl;
    std::cout<<stddev(yAxis_4)<<std::endl;
    std::cout<<stddev(yAxis_5)<<std::endl;
    std::cout<<stddev(yAxis_6)<<std::endl;
    std::cout<<stddev(yAxis_7)<<std::endl;
    std::cout<<stddev(yAxis_8)<<std::endl;
    std::cout<<stddev(yAxis_9)<<std::endl;
    std::cout<<stddev(yAxis_10)<<std::endl;
    std::cout<<stddev(yAxis_11)<<std::endl;
    std::cout<<stddev(yAxis_12)<<std::endl;


    float average = accumulate( yAxis_6.begin(), yAxis_6.end(), 0.0)/yAxis_6.size();
    float average2 = accumulate( yAxis_7.begin(), yAxis_7.end(), 0.0)/yAxis_7.size();

    cv::circle(out2,cv::Point(average,out2.rows/2),25,cv::Scalar(0,255,255),5);
    cv::circle(out2,cv::Point(average2,out2.rows/2),25,cv::Scalar(0,255,255),5);




    cv::imshow("output2",out2);

    cv::waitKey(0);

  return 0;

}
  • Related