【练习8.1】查找轮廓、寻找关键点cvFindDominantPoints、访问序列中的元素
题目要求 | 程序代码 | 结果图片 | 要言妙道 | 借鉴参考 |
查找轮廓并使用 cvFindDominantPoints 寻找关键点,看缩放图像和旋转图像会否影响到IPAN算法的结果
1 // OpenCVExerciseTesting.cpp : 定义控制台应用程序的入口点。 2 // 3 //D:\\Work\\Work_Programming\\Source\\Image\\lena.jpg 4 5 6 #include "stdafx.h" 7 #include<string> 8 #include <cv.h> 9 #include <highgui.h> 10 #include <iostream> 11 12 #include <opencv2/legacy/legacy.hpp> 13 //#pragma comment(lib, "opencv_legacy2411.lib") 14 15 using namespace cv; 16 using namespace std; 17 18 //函数声明-->--->-->--->-->--->-->--->// 19 20 string itos(int i) // 将int 转换成string 21 { 22 stringstream s; 23 s << i; 24 return s.str(); 25 } 26 27 //<--<--<--<--<--<--<--<--<--函数声明// 28 29 int _tmain(int argc, _TCHAR* argv[]) 30 { 31 IplImage * image_Resource; 32 33 string window_name; 34 35 string image_full_name[8]; 36 image_full_name[0] = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第8章\\bracket_mask.jpg"; 37 image_full_name[1] = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第8章\\bracket_mask_80%.jpg"; 38 image_full_name[2] = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第8章\\bracket_mask_120%.jpg"; 39 image_full_name[3] = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第8章\\bracket_mask_15度.jpg"; 40 image_full_name[4] = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第8章\\bracket_mask_-15度60%.jpg"; 41 image_full_name[5] = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第8章\\bracket_mask_-15度.jpg"; 42 image_full_name[6] = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第8章\\bracket_mask_-75度.jpg"; 43 image_full_name[7] = "D:\\Work\\Work_Programming\\Source\\Image\\OpenCVExerciseImage\\第8章\\bracket_mask_105度.jpg"; 44 45 for (int file_name_i = 0; file_name_i < 8; ++file_name_i) 46 { 47 image_Resource = cvLoadImage(image_full_name[file_name_i].c_str(), CV_LOAD_IMAGE_GRAYSCALE); 48 assert(image_Resource); 49 50 IplImage * image_binary = cvCloneImage(image_Resource); 51 cvZero(image_binary); 52 53 //二值化图像 54 double thread_ReturnValue;; 55 thread_ReturnValue = cvThreshold(image_Resource, image_binary, 200, 255, CV_THRESH_BINARY); 56 57 //window_name = "二值图像"; 58 //window_name = window_name + itos(file_name_i); 59 //cvNamedWindow(window_name.data(), CV_WINDOW_AUTOSIZE); 60 //cvShowImage(window_name.data(), image_binary); 61 62 //查找轮廓 63 CvMemStorage * storage = cvCreateMemStorage(); 64 CvSeq * first_contour; 65 int contourNum; 66 contourNum = cvFindContours(image_binary, storage, &first_contour, sizeof(CvContour), CV_RETR_EXTERNAL); 67 68 //显示原始二值图像轮廓 69 IplImage * image_contours = cvCreateImage(cvGetSize(image_binary), IPL_DEPTH_8U, 1); 70 cvZero(image_contours); 71 cvDrawContours(image_contours, first_contour, cvScalar(255), cvScalar(125), 0); 72 window_name = "原始二值图轮廓图像"; 73 window_name = window_name + itos(file_name_i); 74 cvNamedWindow(window_name.data(), CV_WINDOW_AUTOSIZE); 75 cvShowImage(window_name.data(), image_contours); 76 77 //寻找关键点 78 CvSeq *dominant = NULL; 79 CvMemStorage *storate_dominant = cvCreateMemStorage(); 80 dominant = cvFindDominantPoints(first_contour, storate_dominant); 81 82 IplImage *image_dominant = cvCreateImage(cvGetSize(image_contours), IPL_DEPTH_8U, 1); 83 cvZero(image_dominant); 84 85 for (int i = 0; i < dominant->total; ++i) 86 { 87 //cvFindDominantPoints返回的只是索引,所以,用下面两行代码无法画出关键点 88 //CvPoint *point = (CvPoint*)cvGetSeqElem(dominant, i); 89 // cvCircle(image_dominant, *point, 5, cvScalar(255)); 90 91 int idx = *(int *)cvGetSeqElem(dominant, i); 92 CvPoint pt = *(CvPoint *)cvGetSeqElem(first_contour, idx); 93 cvDrawCircle(image_dominant, pt, 1, cvScalar(255)); 94 } 95 96 window_name = "寻找到的关键点"; 97 window_name = window_name + itos(file_name_i); 98 cvNamedWindow(window_name.c_str(), CV_WINDOW_AUTOSIZE); 99 cvShowImage(window_name.c_str(), image_dominant); 100 101 cvReleaseImage(&image_binary); 102 cvReleaseImage(&image_contours); 103 cvReleaseImage(&image_dominant); 104 } 105 106 cvWaitKey(0); 107 108 cvReleaseImage(&image_Resource); 109 110 cvDestroyAllWindows(); 111 112 return 0; 113 }
①:cvFindContours的输入图像必须是8位单通道图像,并且应该被转化为二值的;注意:cvFindContours运行时,这个图像会被直接涂改,所以,注意使用副本。
②cvFindContours的first_contours参数时一个指向CvSeq* 的指针,只需传一个指针即可,无需动手分配内存,也不要分配和释放,cvFindContours函数会自动设置它的值 CvSeq* firstContour = NULL; cvFindContours( …, &firstContour, … );
③ 注意 cvFindDominantPoints 返回的只是关键点在轮廓中的索引,而不是点的序列,如果需要得到关键点的坐标,还需要将该索引传入到 cvGetSeqElem 才可以
④从测试的结果看,缩放会影响IPAN算法返回的结果,特别是当图像的轮廓线不是水平或垂直的时候,旋转也会影响。
‖==========钟于原创 乐于分享 宁静致远 毋忆典藏==========‖