【练习8.10】直接使用cvFindContour的结果图片和cvDrawContour的方式提取Hu矩,观察在图片缩放或旋转时的稳定性

 

页内索引
题目要求 程序代码 结果图片 要言妙道 借鉴参考

 

 

  

题目要求:

 旋转缩放图像

a、使用《学习OpenCV》书中提到的技巧,先使用cvDrawContour绘制找到的轮廓在提取矩

b、直接使用cvFindContour的结果图片提取矩

 

程序代码:

 

  1 // OpenCVExerciseTesting.cpp : 定义控制台应用程序的入口点。

  2 //

  3 //    string file_full_name = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第8章\\r20.jpg";

  4 

  5 

  6 #include "stdafx.h"

  7 #include<string>

  8 #include <cv.h>

  9 #include <highgui.h>

 10 #include <iostream>

 11 #include<math.h>

 12 

 13 #include <opencv2/legacy/legacy.hpp>

 14 //#pragma comment(lib, "opencv_legacy2411.lib")

 15 

 16 using namespace cv;

 17 using namespace std;

 18 

 19 //函数声明-->--->-->--->-->--->-->--->//

 20 //void imRotate(IplImage *src, IplImage *dst, double angle, CvPoint2D32f center, double scale);

 21 

 22 IplImage * ImageZoomOrRotatopn(IplImage * image, double scale=1.0, double angle=0.0);

 23 void CalcHuMoments(IplImage * image_source, string window_name);

 24 void CalcHuMoments2(IplImage * image_source, string window_name);

 25 

 26 //<--<--<--<--<--<--<--<--<--函数声明//

 27 

 28 int _tmain(int argc, _TCHAR* argv[])

 29 {

 30     string file_full_name = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第8章\\字符A.jpg";

 31     IplImage * image_source = cvLoadImage(file_full_name.c_str(), CV_LOAD_IMAGE_GRAYSCALE);

 32     CV_Assert(image_source);

 33     

 34     //原始图像

 35     string window_name = "字符A原始图像";

 36     CalcHuMoments(image_source, window_name);

 37 

 38 

 39     //旋转图像

 40     IplImage *image_1 = ImageZoomOrRotatopn(image_source, 1.0, 73);

 41     window_name = "字符A旋转73度图像";

 42     CalcHuMoments(image_1, window_name);

 43 

 44     //缩放图像

 45     IplImage *image_2 = ImageZoomOrRotatopn(image_source, 1.5, 0.0);

 46     window_name = "字符A放大1.5倍图像";

 47     CalcHuMoments(image_2, window_name);

 48 

 49 

 50     file_full_name = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第8章\\字符F.jpg";

 51     IplImage * image_other = cvLoadImage(file_full_name.c_str(), CV_LOAD_IMAGE_GRAYSCALE);

 52     CV_Assert(image_other);

 53 

 54     //其它图像测试

 55     window_name = "其它图像";

 56     CalcHuMoments(image_other, window_name);

 57 

 58     //==============================================================================

 59 

 60     cout << endl << endl;

 61 

 62     //不使用cvDrawContour画的轮廓计算矩,直接使用cvFindContour的结果

 63     IplImage * image_temp = cvCloneImage(image_source);

 64     CalcHuMoments2(image_temp, window_name);

 65 

 66     CalcHuMoments2(image_1, window_name);

 67 

 68     CalcHuMoments2(image_2, window_name);

 69 

 70     CalcHuMoments2(image_other, window_name);

 71 

 72     //system("pause");

 73     cvWaitKey(0);

 74 

 75     //cvReleaseImage(&image_source);

 76     //cvReleaseImage(&image_source_2);

 77     cvDestroyAllWindows();

 78 

 79     return 0;

 80 }

 81 

 82 IplImage * ImageZoomOrRotatopn(IplImage * image, double scale, double angle)

 83 {

 84     IplImage * affinedImage = cvCloneImage(image);

 85     CvMat *rot_mat = cvCreateMat(2, 3, CV_32FC1);

 86     CvPoint2D32f center = cvPoint2D32f(image->width / 2, image->height / 2);

 87     cv2DRotationMatrix(center, angle, scale, rot_mat);

 88     cvWarpAffine(image, affinedImage, rot_mat);

 89     return affinedImage;

 90 }

 91 

 92 void CalcHuMoments(IplImage * image_source,string window_name)

 93 {

 94     CvMoments moments;

 95     CvHuMoments  Hu_moments;

 96     IplImage * image_contour = cvCloneImage(image_source);

 97     cvZero(image_contour);

 98 

 99     IplImage * image_binary = cvCloneImage(image_source);

100     cvZero(image_binary);

101     cvThreshold(image_source, image_binary, 100, 255, CV_THRESH_BINARY);//重要,调用从vFindContour前先二值化图像

102 

103     CvMemStorage *storage = cvCreateMemStorage();

104     CvSeq * first_contour=NULL;

105     int contour_num;

106     contour_num = cvFindContours(image_binary, storage, &first_contour);// , sizeof(CvContour), CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);

107     cvDrawContours(image_contour, first_contour, cvScalar(255), cvScalar(255), 5);//重要,将轮廓绘制到图像,供下一步调用

108 

109     cvShowImage(window_name.c_str(), image_contour);

110 

111     cvMoments(image_contour, &moments, 1);

112     cvGetHuMoments(&moments, &Hu_moments);

113     cout << window_name<< "Hu矩结果:" << endl;

114     cout << setiosflags(ios::scientific) << setprecision(4) << Hu_moments.hu1 << " ";

115     cout << Hu_moments.hu2 << " ";

116     cout << Hu_moments.hu3 << " ";

117     cout << Hu_moments.hu4 << " ";

118     cout << Hu_moments.hu5 << " ";

119     cout << Hu_moments.hu6 << " ";

120     cout << Hu_moments.hu7 << endl;

121 

122     //cout << "(" << setprecision(3) << dec <</* scalar <<*/ ")" << " ";

123     //for (int i = 0; i<7; ++i){

124     //    cout << setiosflags(ios::scientific) << setprecision(4) << ((double*)&Hu_moments)[i] << ' ';

125     //}

126     //cout << endl;

127 

128     cvReleaseImage(&image_contour);

129     cvReleaseImage(&image_binary);

130     cvClearSeq(first_contour);

131     cvReleaseMemStorage(&storage);

132 }

133 

134 void CalcHuMoments2(IplImage * image_source, string window_name)

135 {

136     CvMemStorage *storage = cvCreateMemStorage();

137     CvSeq * contour = NULL;

138 

139     cvThreshold(image_source, image_source, 100, 255, CV_THRESH_BINARY);

140 

141     cvFindContours(image_source, storage, &contour);

142     //cvShowImage(window_name.c_str(), image_source);

143     CvMoments moments;

144     CvHuMoments huMoments;

145     cvMoments(image_source, &moments, 1);

146     cvGetHuMoments(&moments, &huMoments);

147 

148     cout << "CalcHuMoments2输出" << endl;

149     ////cout << "(" << setprecision(3) << dec << scalar << ")" << " ";

150     //for (int i = 0; i<7; ++i){

151     //    cout << setiosflags(ios::scientific) << setprecision(4) << ((double*)&huMoments)[i] << ' ';

152     //}

153     //cout << endl;

154     cout << window_name << "Hu矩结果:" << endl;

155     cout << setiosflags(ios::scientific) << setprecision(4) << huMoments.hu1 << " ";

156     cout << huMoments.hu2 << " ";

157     cout << huMoments.hu3 << " ";

158     cout << huMoments.hu4 << " ";

159     cout << huMoments.hu5 << " ";

160     cout << huMoments.hu6 << " ";

161     cout << huMoments.hu7 << endl;

162 

163     cvClearSeq(contour);

164     cvReleaseMemStorage(&storage);

165 }

166 

167 //void imRotate(IplImage *src, IplImage *dst, double angle, CvPoint2D32f center, double scale)

168 //{

169 //    assert(src->width == dst->width && src->height == dst->height &&src->depth == dst->depth &&src->nChannels == dst->nChannels);

170 //    CvMat *mapMatrix = cvCreateMat(2, 3, CV_32FC1);

171 //    cv2DRotationMatrix(center, angle, scale, mapMatrix); //旋转缩放为仿射变换,此处求变换矩阵

172 //

173 //    cvWarpAffine(src, dst, mapMatrix);

174 //}

 

 

结果图片:

【练习8.10】直接使用cvFindContour的结果图片和cvDrawContour的方式提取Hu矩,观察在图片缩放或旋转时的稳定性
【练习8.10】直接使用cvFindContour的结果图片和cvDrawContour的方式提取Hu矩,观察在图片缩放或旋转时的稳定性

 

要言妙道:

 ①函数 cvFindContours 从二值图像寻找图像。此二值图像可以是从cvCanny函数得到的有边缘像素的图像,或者是从cvThreshold及cvAdaptiveThreshold得到的图像,这时的边缘是正合负区域之间的边界。如果在cvFindContours前没有二值化图像,会发现本练习第一个原始图像找轮廓后画出的轮廓没有结果,而且最后的hu矩完全无规律

② 一个有用的小技巧是:用从vDrawContour描绘一幅轮廓的图像后,调用一个矩的处理函数处理该图像

③再次强调 cvFindContour 的输入图像会直接被涂改

 

 

借鉴参考:

 

你可能感兴趣的:(find)