4

In some reason google does not have good examples of using cvCalcPGH() nor other good examples of using Freeman code for contour matching. So I try to make it:

#include "opencv2/opencv.hpp"
#include "opencv2/legacy/legacy.hpp"

int
main(int argc, char* argv[]) {

        IplImage* g_gray = cvLoadImage("lisa.png",CV_LOAD_IMAGE_GRAYSCALE);
        cvThreshold( g_gray, g_gray, 100, 255, CV_THRESH_BINARY );

        CvMemStorage* storage=cvCreateMemStorage(0);
        CvSeq* firstContour=NULL;

        int a=cvFindContours(g_gray, storage, &firstContour,sizeof(CvChain),CV_RETR_LIST, CV_CHAIN_CODE);

        CvHistogram *hist;
        int h_bins = 30, s_bins = 30;
        float h_ranges[] = { 0, 180 };
        float s_ranges[] = { 0, 255 };
        int hist_size[] = { h_bins, s_bins };
        float* ranges[] = { h_ranges, s_ranges };

        hist = cvCreateHist( 2, hist_size, CV_HIST_ARRAY, ranges, 1 );
        if( CV_SEQ_ELTYPE( firstContour ) != CV_32SC2 ) {
                printf(":(\n");
        }

        cvCalcPGH((CvSeq *)firstContour,hist);
        return 0;

}

cvFindContours() will run as documented but cvCalcPGH() will fail:

$ ./calcpgh 
:(
OpenCV Error: Unsupported format or combination of formats (The contour is not valid or the point type is not supported) in cvCalcPGH, file /Users/tonu-samuel/OpenCV-2.4.2/modules/legacy/src/pgh.cpp, line 351
terminate called throwing an exceptionAbort trap: 6
$

OpenCV is 2.4.2 and indicated assert() is for CV_SEQ_ELTYPE( contour ) != CV_32SC2 I check also in my code. How to fix it unsure.

Tõnu Samuel
  • 2,877
  • 2
  • 20
  • 30

1 Answers1

6

The reason google won't give you good examples, is all the things you are talking about are deprecated.

cvCalcPGH is not anymore available in the new opencv, which you may already know as you have included legacy libraries.

Also the CV_CHAIN_CODE is removed and you can't use it in the new opencv.

You should find the time to port your code to the new opencv which is trending and will get more help from others.

But discussing your current code, as the old documentation says:

CV_CHAIN_CODE - outputs contours in the Freeman chain code. All other methods output polygons (sequences of vertices)

The output of cvFindContours is always sequences of vertices and CV_CHAIN_CODE is just an exception. That's why cvCalcPGH couldn't understand these codes.

And as you may have already tested the code with other approximation methods, you should've seen that the cvCalcPGH works fine with polygons.

You should convert the Freeman code to polygons yourself, then you can use any opencv methods you want. But without that, I have not seen a single method that can interpret the Freeman code itself.

I'm not sure how exactly this conversion should be done, but using the code below, which is shamelessly stolen from Sara Maher Mohammad, you may extract the codes and start interpreting it yourself:

CvChainPtReader reader;

cvStartReadChainPoints((CvChain*) firstContour, &reader);
for (int i = 0; i < firstContour->total; i++) {
    CV_READ_SEQ_ELEM(reader.code, (*((CvSeqReader*)&(reader))));
    printf("%d \n", reader.code);
}

But again, I don't recommend working on deprecated methods and functions, you may find better ways to do what you want.

Just guessing that you may just want to find the distance between two Freeman codes, you may just stay out of calculating PGH, and just use some other distance functions like the one discussed here.

Community
  • 1
  • 1
Kamyar Infinity
  • 2,711
  • 1
  • 21
  • 32