首页 > 代码库 > 在图片上画矩形并高亮显示矩形区域、统计矩形区域中像素情况并绘制直方图

在图片上画矩形并高亮显示矩形区域、统计矩形区域中像素情况并绘制直方图

《学习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 }

 

结果图片: