首页 > 代码库 > 在图片上画矩形并高亮显示矩形区域、统计矩形区域中像素情况并绘制直方图
在图片上画矩形并高亮显示矩形区域、统计矩形区域中像素情况并绘制直方图
《学习OpenCV》中文版第4章第3题
题目要求 |
程序代码 |
结果图片 |
题目要求:
①允许用户在图片上选择一个矩形区域,当鼠标放开,高亮显示矩形区域
②在另一个独立窗口中,使用绘图函数绘制一个图表,分别用蓝、绿和红色表示选中区域中各种颜色的像素在指定数值范围内的数量。
程序代码:
1 #include "stdafx.h" 2 #include <cv.h> 3 #include <highgui.h> 4 using namespace std; 5 using namespace cv; 6 7 //函数声明-->--->-->--->-->--->-->--->// 8 9 void MouseCallBack(int event, int x, int y, int flags, void *param); 10 void HighLight(IplImage * img, CvRect *rect); 11 void DrawHistogram(IplImage * colorImage, CvRect *rect, IplImage * imgHistogram); 12 int RangeCalculate(int value); 13 14 //<--<--<--<--<--<--<--<--<--函数声明// 15 16 CvRect box; 17 bool drawingBox = false; 18 19 void DrawBox(IplImage *img, CvRect rect) 20 { 21 cvRectangle(img, cvPoint(rect.x, rect.y), cvPoint(rect.x + rect.width, rect.y + rect.height), cvScalar(255, 0, 0)); 22 } 23 24 int _tmain(int argc, _TCHAR* argv[]) 25 { 26 box = cvRect(-1, -1, 0, 0); 27 28 const char * fileName = "D:\\Work\\Work_Programming\\Source\\Image\\introduction.jpg"; 29 IplImage * img = cvLoadImage(fileName, CV_LOAD_IMAGE_UNCHANGED); 30 IplImage *drawHistogram = cvCreateImage(cvSize(240, img->width*img->height), IPL_DEPTH_8U, 3); 31 32 cvNamedWindow("ExerciseWindow", CV_WINDOW_AUTOSIZE); 33 cvNamedWindow("区域直方图", 0); 34 35 assert(img && drawHistogram); 36 37 cvSetZero(drawHistogram); 38 drawHistogram->origin = IPL_ORIGIN_BL; //将图片原点设置为左下角 39 40 IplImage * temp=cvCloneImage(img); 41 IplImage * tempHist = cvCloneImage(drawHistogram); 42 cvSetMouseCallback("ExerciseWindow", MouseCallBack, temp); 43 44 while (true) 45 { 46 if (drawingBox) 47 { 48 cvCopyImage(img, temp); 49 DrawBox(temp, box); 50 51 cvCopyImage(drawHistogram, tempHist); 52 DrawHistogram(img, &box, tempHist); 53 } 54 55 cvShowImage("ExerciseWindow", temp); 56 cvShowImage("区域直方图", tempHist); 57 58 if (waitKey(15) == 27) 59 { 60 break; 61 } 62 } 63 64 cvWaitKey(0); 65 66 cvReleaseImage(&img); 67 cvReleaseImage(&drawHistogram); 68 cvReleaseImage(&temp); 69 cvReleaseImage(&tempHist); 70 cvDestroyWindow("区域直方图"); 71 cvDestroyWindow("ExerciseWindow"); 72 73 return 0; 74 } 75 76 //鼠标事件回调函数 77 void MouseCallBack(int event, int x, int y, int flags, void *param) 78 { 79 IplImage * img = (IplImage *)param; 80 81 switch (event) 82 { 83 case CV_EVENT_LBUTTONDOWN: 84 { 85 drawingBox = true; 86 box = cvRect(x, y, 0, 0); 87 } 88 break; 89 case CV_EVENT_MOUSEMOVE: 90 { 91 if (drawingBox) 92 { 93 box.width = x - box.x; 94 box.height = y - box.y; 95 } 96 } 97 break; 98 case CV_EVENT_LBUTTONUP: 99 { 100 drawingBox = false;101 if (box.width < 0)102 {103 box.x += box.width;104 box.width *= -1;105 }106 if (box.height < 0)107 {108 box.y += box.height;109 box.height *= -1;110 }111 HighLight(img, &box);112 }113 break;114 default:115 break;116 } 117 }118 119 //高亮显示矩形区域120 void HighLight(IplImage * img, CvRect *rect)121 {122 int startX = rect->x;123 int startY = rect->y;124 int boxWidth = rect->width;125 int boxHeight = rect->height;126 127 for (int h = startY; h < (startY+boxHeight); ++h)128 {129 uchar *ptr = (uchar *)(img->imageData + h*img->widthStep); 130 for (int w = startX; w < (startX+boxWidth); ++w)131 {132 ptr[3 * w + 2] = 255;133 }134 }135 }136 137 //统计矩形区域内像素情况并绘制直方图138 void DrawHistogram(IplImage * colorImage,CvRect *rect,IplImage * imgHistogram)139 {140 int arrCountB[8]; //存储B通道值在0-31、32-63....223-255这八段各段像素的个数141 int arrCountG[8];142 int arrCountR[8];143 144 for (int i = 0; i < 8; ++i)145 {146 arrCountB[i] = 0;147 arrCountG[i] = 0;148 arrCountR[i] = 0;149 }150 151 int startX = rect->x;152 int startY = rect->y;153 int boxWidth = rect->width;154 int boxHeight = rect->height;155 156 for (int h = startY; h < (startY + boxHeight); ++h)157 {158 uchar *ptr = (uchar *)(colorImage->imageData + h*colorImage->widthStep);159 for (int w = startX; w < (startX + boxWidth); ++w)160 {161 int rangeB = RangeCalculate(ptr[3 * w + 0]); //判断B通道的当前值在哪个范围内,就将对应的arrCountB数组元素加一162 arrCountB[rangeB]++;163 164 int rangeG = RangeCalculate(ptr[3 * w + 1]);165 arrCountG[rangeG]++;166 167 int rangeR = RangeCalculate(ptr[3 * w + 2]);168 arrCountR[rangeR]++;169 }170 }171 172 int histWidth = 10;173 174 //分别绘制八个区间B、G、R柱175 for (int i = 0; i < 8; ++i)176 {177 cvRectangleR(imgHistogram, cvRect(3 * histWidth*i, 0, histWidth, arrCountB[i]), cvScalar(255, 0, 0), CV_FILLED);178 cvRectangleR(imgHistogram, cvRect(3 * histWidth*i + histWidth, 0, histWidth, arrCountG[i]), cvScalar(0, 255, 0), CV_FILLED);179 cvRectangleR(imgHistogram, cvRect(3 * histWidth*i + 2*histWidth, 0, histWidth, arrCountR[i]), cvScalar(0, 0, 255), CV_FILLED);180 } 181 }182 183 //判断值所在的区域段184 int RangeCalculate(int value)185 {186 if (value >= 0 && value <= 31)187 {188 return 0;189 }190 191 if (value >= 32 && value <= 63)192 {193 return 1;194 }195 196 if (value >= 64 && value <= 95)197 {198 return 2;199 }200 201 if (value >= 96 && value <= 127)202 {203 return 3;204 }205 206 if (value >= 128 && value <= 159)207 {208 return 4;209 }210 211 if (value >= 160 && value <= 191)212 {213 return 5;214 }215 216 if (value >= 192 && value <= 223)217 {218 return 6;219 }220 221 if (value >= 224 && value <= 255)222 {223 return 7;224 }225 }
结果图片:
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。