zoukankan      html  css  js  c++  java
  • 【练习4.3】在图片上画矩形并高亮显示矩形区域、统计矩形区域中像素情况并绘制直方图

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

    结果图片:

    ‖==========钟于原创 乐于分享 宁静致远 毋忆典藏==========‖
  • 相关阅读:
    第三次冲刺
    第二次冲刺
    第一次冲刺
    团队学习
    git and github
    还不够格的程序员
    CF1602F. Difficult Mountain
    线性基
    欧拉回路学习笔记
    莫比乌斯反演-学习笔记
  • 原文地址:https://www.cnblogs.com/tingshuixuan2012/p/OpenCVExercises4_3.html
Copyright © 2011-2022 走看看