OpenCV (C): расчет моментов ИЗ контура

Вот код, который у меня есть:

#include "highgui.h"
#include "cv.h"  
#include <stdio.h>

// this code finds contours

int main (int argc, char* argv[]) {
  cvNamedWindow( argv[0], 1 );

  IplImage* img_8uc1 = cvLoadImage( argv[1], CV_LOAD_IMAGE_GRAYSCALE );
  IplImage* img_edge = cvCreateImage( cvGetSize(img_8uc1), 8, 1);
  IplImage* img_8uc3 = cvCreateImage( cvGetSize(img_8uc1), 8, 3);

  cvThreshold( img_8uc1, img_edge, 128, 255, CV_THRESH_BINARY );

  CvMemStorage* storage = cvCreateMemStorage();
  CvSeq* first_contour = NULL;
  int Nc = cvFindContours(img_edge, storage, &first_contour,
              sizeof(CvContour), CV_RETR_LIST );

  int n = 0;
  printf("Total Contours Detected: %d\n", Nc);
  CvSeq* c=first_contour;
  for( c; c!=NULL; c=c->h_next ) {
    cvCvtColor( img_8uc1, img_8uc3, CV_GRAY2BGR );
    cvDrawContours(img_8uc3, c, 
           CV_RGB(250,0,0), //red
           CV_RGB(0,0,250), //blue
           0,2,8);
    printf("Contour #%d\n", n);
    cvShowImage( argv[0], img_8uc3 );
    printf(" %d elements:\n", c->total );
    for( int i=0; i<c->total; ++i) {
      CvPoint* p = CV_GET_SEQ_ELEM(CvPoint, c, i);
      printf("     (%d,%d)\n", p->x, p->y); 
    }
    cvWaitKey(0);
    n++;
  }


  // moments
  CvMoments* Moments;
  CvHuMoments *HuMoments;
  // calculate moments; calculate humoments
  cvContourMoments(c, Moments);
  cvGetHuMoments(Moments, HuMoments);

  //print the hu moments
  printf("Hu Moment hu1: %.12f", HuMoments->hu1);
  printf("Hu Moment hu2: %.12f", HuMoments->hu2);
  printf("Hu Moment hu3: %.12f", HuMoments->hu3);
  printf("Hu Moment hu4: %.12f", HuMoments->hu4);
  printf("Hu Moment hu5: %.12f", HuMoments->hu5);
  printf("Hu Moment hu6: %.12f", HuMoments->hu6);
  printf("Hu Moment hu7: %.12f", HuMoments->hu7);


  printf("Finished all contours.\n");
  cvCvtColor(img_8uc1, img_8uc3, CV_GRAY2BGR);
  cvShowImage(argv[0], img_8uc3);
  cvWaitKey(0);

  cvDestroyWindow(argv[0]);
  cvReleaseImage(&img_8uc1);
  cvReleaseImage(&img_8uc3);
  cvReleaseImage(&img_edge);

  return 0;
}

По сути, первая половина кода и последние строки кода взяты непосредственно из книги «Изучение OpenCV», так как это уже делает поиск контура, и это то, что я хочу (не плагиат, я что-то пробую), а средняя часть кода (как задокументировано) посвящена вычислению Hu Moments. Я хочу попытаться увидеть, изменяются ли какие-либо значения моментов, когда конкретное изображение с контуром ориентировано по-разному или когда изменяется размер изображения.

Я думал, что написал это правильно, по крайней мере, алгоритм мне показался правильным, но я продолжаю получать это сообщение об ошибке:

Ошибка OpenCV: нулевой указатель () в cvMoments, файл /build/buildd/opencv-2.1.0/src/cv/cvmoments.cpp, строка 343, завершается после создания экземпляра 'cv::Exception' what():/ build/buildd/opencv-2.1.0/src/cv/cvmoments.cpp:343: ошибка: (-27) в функции cvMoments

Прервано

Есть ли проблема в том, как я использовал структуру данных CvMoments, или проблема связана с функцией CvContourMoments()? Версия OpenCV, которую я использовал в настоящее время, — 2.1.0.

Я ценю помощь! я не могу найти подобные решения нигде в Интернете, и мне интересно, есть ли у кого-нибудь аналогичная проблема с расчетом момента по контурам.


person Vincent Lu    schedule 30.12.2011    source источник


Ответы (3)


Я думаю, вы должны определить момент структуры вместо указателя.

Попробуй это:

CvMoments Moments;
CvHuMoments HuMoments;
// calculate moments; calculate humoments
cvContourMoments(c, &Moments);
cvGetHuMoments(&Moments, &HuMoments);
//print the hu moments
printf("Hu Moment hu1: %.12f", HuMoments.hu1);
printf("Hu Moment hu2: %.12f", HuMoments.hu2);
printf("Hu Moment hu3: %.12f", HuMoments.hu3);
printf("Hu Moment hu4: %.12f", HuMoments.hu4);
printf("Hu Moment hu5: %.12f", HuMoments.hu5);
printf("Hu Moment hu6: %.12f", HuMoments.hu6);
printf("Hu Moment hu7: %.12f", HuMoments.hu7);

Кстати, cvContourMoments() похоже на cvMoments(). Я могу найти только cvMoments() на http://www.opencv.org.cn/opencvdoc . А переменная "c" должна быть указателем на IplImage или CvArr.

Я новый. Желание помочь.

person xiaofang    schedule 30.12.2011
comment
Спасибо за ответ! Хотя я думаю, что разница между cvCOntourMoments() и cvMOments заключается в аргументах, которые они принимают. Первая функция принимает в качестве аргумента фактический контур, а вторая — изображение. Я просто использовал ваше предложение выше, и все остальное то же самое, за исключением того, что я попробовал другой подход: вместо вычисления момента из контура c я вызвал функцию cvMoments() с изображением img_8uc3, потому что контуры рисуются на этом изображении. Но в этот раз получаю ошибку (ошибку напишу в следующем посте). Любые другие предложения? - person Vincent Lu; 31.12.2011
comment
Ошибка OpenCV: неверный флаг (параметр или поле структуры) (нераспознанный или неподдерживаемый тип массива) в cvGetMat, файл /build/buildd/opencv-2.1.0/src/cxcore/cxarray.cpp, строка 2476, завершение вызова после создания экземпляра 'cv::Exception' what(): /build/buildd/opencv-2.1.0/src/cxcore/cxarray.cpp:2476: ошибка: (-206) Нераспознанный или неподдерживаемый тип массива в функции cvGetMat Aborted - person Vincent Lu; 31.12.2011

Я думаю, вы пропустили, чтобы указать, какой образ будет тестироваться. Я тоже новичок, но вы можете попробовать Программу, которую я тестировал, чтобы получить контуры (это работает :)), и оттуда вы можете добавить функцию для получения моментов контуров. Я надеюсь, это поможет вам.

person Knighk    schedule 28.01.2012

вы забыли сбросить c;

Попробуйте добавить

c=first_contour;

прежде чем использовать его в

cvContourMoments(c, &Moments);; 
person Mantale    schedule 25.02.2014