opencv/javacv: How to iterate over contours for shape identification?

前端 未结 3 783

I\'m developing a shape identification project using JavaCV and I have found some OpenCV code to identify U shapes in a particular image. I have tried to convert it into JavaCV

相关标签:
3条回答
  • 2021-02-08 17:33

    This code work for me and I just put cvSeq=cvSeq.h_next(); line in to the program and remove the for loop add while loop for thet.

        package Beam;
        import com.googlecode.javacpp.Loader;
        import com.googlecode.javacv.CanvasFrame;
        import static com.googlecode.javacpp.Loader.*;
        import static com.googlecode.javacv.cpp.opencv_core.*;
        import static com.googlecode.javacv.cpp.opencv_imgproc.*;
        import static com.googlecode.javacv.cpp.opencv_highgui.*;
        import java.io.File;
        import javax.swing.JFileChooser;
    
        public class TestBeam2 {
            public static void main(String[] args) {
                JFileChooser f=new JFileChooser();
                int result=f.showOpenDialog(f);//show dialog box to choose files
                    File myfile=null;
                    String path="";
                if(result==0){
                    myfile=f.getSelectedFile();//selected file taken to myfile
                    path=myfile.getAbsolutePath();//get the path of the file
                }
                IplImage src = cvLoadImage(path);//hear path is actual path to image
                IplImage grayImage    = IplImage.create(src.width(), src.height(), IPL_DEPTH_8U, 1);
                cvCvtColor(src, grayImage, CV_RGB2GRAY);
                cvThreshold(grayImage, grayImage, 127, 255, CV_THRESH_BINARY);
                CvSeq cvSeq=new CvSeq();
                CvMemStorage memory=CvMemStorage.create();
                cvFindContours(grayImage, memory, cvSeq, Loader.sizeof(CvContour.class), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
    
                while (cvSeq != null && !cvSeq.isNull()) {
                    CvRect rect=cvBoundingRect(cvSeq, 0);
                    int x=rect.x(),y=rect.y(),h=rect.height(),w=rect.width();
                    if (10 < w/h || w/h < 0.1){
                        cvRectangle(src, cvPoint(x, y), cvPoint(x+w, y+h), CvScalar.RED, 1, CV_AA, 0);
                    }
                    cvSeq=cvSeq.h_next();
                }
                CanvasFrame cnvs=new CanvasFrame("Beam");
                cnvs.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
                cnvs.showImage(src);
                //cvShowImage("Final ", src);
            }
        }
    
    0 讨论(0)
  • 2021-02-08 17:41

    Check your type promotions, e.g.:

    if (10 < (w/h) || (w/h) < 0.1){
    

    .. is highly suspect. To get a floating point division, one (or both) of the operands must at least be a float (and likewise a double for double division). Otherwise, as in this case, it is an integer division. (Note that the original code has promotion to float as well.)

    For instance:

     float ratio = (float)w/h; // (float / int) => (float / float) -> float
     if (10 < ratio || ratio < 0.1 ) { 
    

    (Although I am unsure if this is the issue here.)

    Happy coding!

    0 讨论(0)
  • 2021-02-08 17:48

    EDIT: Here is the most interesting finding - I think you are not iterating correctly through the contours - you should do something like:

    CvRect rect = cvBoundingRect(cvGetSeqElem(cvSeq, i),0); //python default?
    

    Or:

    // ... 
    CvSeq contours = new CvSeq();
    CvSeq ptr = new CvSeq();
    CvRect rect = null;
    // ...
    cvFindContours(..., contours, ...);
    
    for (ptr = contours; ptr != null; ptr = ptr.h_next()) {
        rect =  cvBoundingRect(ptr, 0);
        // ... Draw the box if meets criteria
    }
    

    First, I think pst is right regarding the calculation of the ratio - you have to cast the width to float.

    Secondly, I see that when you are making the gray image in python you use COLOR_BGR2GRAY and in java you are using CV_RGB2GRAY that could lead to a totally different gray picture. I would add some debug steps on both programs to save the temp gray images and compare them as also print outs for the values of x,y,w and h when (10 < (w/h) || (w/h) < 0.1) is true.

    Another thing is that in the java solution you use CV_RETR_CCOMP to get the contours and in the python solution you use CV_RETR_LIST according to the documentation:

    CV_RETR_LIST retrieves all of the contours without establishing any hierarchical relationships CV_RETR_CCOMP retrieves all of the contours and organizes them into a two-level hierarchy: on the top level are the external boundaries of the components, on the second level are the boundaries of the holes. If inside a hole of a connected component there is another contour, it will still be put on the top level

    So first I would double check that all cv's parameters in both programs are the same, then I would add debug steps to see that the intermediate variables contains the same data.

    0 讨论(0)
提交回复
热议问题