《学习OpenCV》练习题第四章第三题b

  1 #include <highgui.h>
  2 #include <cv.h>
  3 #include "opencv_libs.h"
  4 
  5 /*
  6  *《学习OpenCV》第四章第三题b
  7  * 完成时间:1:36 3/31 星期日 2013
  8  */
  9 
 10 /* 矩形框 */
 11 CvRect rect;
 12 
 13 bool draw = false;   // 标记是否在画
 14 
 15 IplImage* img;
 16 IplImage * temp;
 17 IplImage * original;
 18 
 19 bool draw_hist = false;
 20 
 21 IplImage* getHistImage(IplImage* image, CvHistogram* image_hist, 
 22                        CvSize image_size, CvScalar value)
 23 {
 24     // 计算直方图
 25     cvCalcHist( &image, image_hist, 0, NULL );
 26     // 新建一幅3通道的图像
 27     IplImage* dst = cvCreateImage(image_size, IPL_DEPTH_8U, 3 );
 28     
 29     cvSet( dst, cvScalarAll(255) );
 30     
 31     float max_value = 0;
 32     cvGetMinMaxHistValue( image_hist, NULL, &max_value, NULL, NULL );
 33     double bin_width = (double)dst->width/256;
 34     double bin_unith = (double)dst->height/max_value;   // 高度比例
 35 
 36     for(int i = 0; i < 256; i++)
 37     {
 38         // 获得矩形左上角和右下角坐标
 39         CvPoint p0 = cvPoint( i + bin_width, dst->height );
 40         CvPoint p1 = cvPoint( (i+1) * bin_width, 
 41             dst->height - cvGetReal1D(image_hist->bins, i) *  bin_unith );
 42         // 画实心矩形
 43         cvRectangle( dst, p0, p1, value, -1, 8, 0 );
 44     }
 45 
 46     return dst;
 47 }
 48 
 49 void draw_rect(IplImage* img, CvRect rect)
 50 {
 51     cvRectangle( img, 
 52         cvPoint( rect.x, rect.y ),
 53         cvPoint( rect.x + rect.width, rect.y + rect.height),
 54         cvScalar( 0x00, 0x00, 0xff) );
 55     printf("draw
");
 56 
 57     // 在这里处理直方图
 58     // 设置感兴趣区域
 59     cvSetImageROI( img, rect);
 60     IplImage* src_rect = cvCreateImage ( 
 61         cvSize( rect.width, rect.height ), 
 62         img->depth, img->nChannels );
 63     cvCopy(img, src_rect );
 64     cvResetImageROI( img );
 65 
 66     IplImage* r_img = cvCreateImage( cvGetSize( src_rect),
 67         src_rect->depth, 1 );
 68     IplImage* g_img = cvCreateImage( cvGetSize( src_rect),
 69         src_rect->depth, 1 );
 70     IplImage* b_img = cvCreateImage( cvGetSize( src_rect),
 71         src_rect->depth, 1 );
 72     IplImage* gray_img = cvCreateImage( cvGetSize( src_rect),
 73         src_rect->depth, 1 );
 74     
 75     // 分离RGB分量
 76     cvSplit( src_rect, r_img, g_img, b_img, NULL);
 77     cvShowImage( "red", r_img);
 78     cvShowImage( "green", g_img);
 79     cvShowImage( "blue", b_img);
 80     
 81     // 灰度转换
 82     cvCvtColor( src_rect, gray_img, CV_BGR2GRAY);
 83     int size = 256;
 84     float range[] = {0, 255};
 85     float* ranges[] = {range};
 86     // 创建直方图
 87     CvHistogram * r_hist = cvCreateHist( 1, &size, CV_HIST_ARRAY, ranges, 1);
 88     CvHistogram * g_hist = cvCreateHist( 1, &size, CV_HIST_ARRAY, ranges, 1);
 89     CvHistogram * b_hist = cvCreateHist( 1, &size, CV_HIST_ARRAY, ranges, 1);
 90     CvHistogram * gray_hist = cvCreateHist( 1, &size, CV_HIST_ARRAY, ranges, 1);
 91 
 92     // 直方图尺寸
 93     CvSize image_size = cvSize( 400, 300);
 94     
 95     IplImage* r_dst = getHistImage(r_img, r_hist, image_size, cvScalar(0x00, 0x00, 0xff));
 96     IplImage* g_dst = getHistImage(g_img, g_hist, image_size, cvScalar(0x00, 0xff, 0x00));
 97     IplImage* b_dst = getHistImage(b_img, b_hist, image_size, cvScalar(0xff, 0x00, 0x00));
 98     IplImage* gray_dst = getHistImage( gray_img, gray_hist, image_size, cvScalar(0) );
 99 
100     // 把四个直方图在一幅图片上显示出来
101     IplImage* dst = cvCreateImage( cvSize( image_size.width * 2, image_size.height * 2), 8, 3 );
102     cvSetZero( dst );
103     // 拷贝红色分量直方图
104     CvRect r_rect = cvRect( 0, 0, image_size.width, image_size.height);
105     cvSetImageROI(dst, r_rect);
106     cvCopy( r_dst, dst);
107     // 拷贝绿色分量直方图
108     CvRect g_rect = cvRect(image_size.width, 0, image_size.width, image_size.height );
109     cvSetImageROI( dst, g_rect);
110     cvCopy( g_dst, dst);
111     // 蓝色分量
112     CvRect b_rect = cvRect(0, image_size.height, image_size.width, image_size.height );
113     cvSetImageROI(dst, b_rect);
114     cvCopy( b_dst, dst );
115     // 灰度分量
116     CvRect gray_rect = cvRect( image_size.width, image_size.height, 
117         image_size.width, image_size.height );
118     cvSetImageROI( dst, gray_rect);
119     cvCopy( gray_dst, dst);
120 
121     cvResetImageROI( dst );
122 
123     cvShowImage( "src", src_rect);
124     cvShowImage( "dst", dst );
125 
126     cvWaitKey(0);
127 
128     cvDestroyAllWindows();
129     cvReleaseImage( &r_img );
130     cvReleaseImage(&g_img);
131     cvReleaseImage(&b_img);
132     cvReleaseImage(&gray_img);
133     cvReleaseImage(&r_dst);
134     cvReleaseImage(&g_dst);
135     cvReleaseImage(&b_dst);
136     cvReleaseImage(&gray_dst);
137     cvReleaseImage(&src_rect);
138     cvReleaseImage(&dst);
139 }
140 
141 // 鼠标回调函数
142 void my_mouse_callback( int event, int x, int y, int flags, void* param)
143 {
144     IplImage* image = (IplImage*) param;
145 
146     switch( event )
147     {
148     case CV_EVENT_MOUSEMOVE:
149         {
150             if(draw)
151             {
152                 rect.width = x - rect.x;
153                 rect.height = y - rect.y;
154             }
155 
156             draw_hist = false;
157         }
158         break;
159     case CV_EVENT_LBUTTONDOWN:
160         {
161             draw = true;
162             rect = cvRect( x, y, 0, 0 );
163             draw_hist = false;
164         }
165         break;
166     case CV_EVENT_LBUTTONUP:
167         {
168             draw = false;
169             draw_hist = true;
170             if(rect.width < 0)
171             {
172                 rect.x += rect.width;
173                 rect.width *= -1;
174             }
175             if(rect.height < 0)
176             {
177                 rect.y += rect.height;
178                 rect.height *= -1;
179             }
180             // draw
181             draw_rect(image, rect);
182         }
183         break;
184         // 在右键按下时清除
185     case CV_EVENT_RBUTTONDOWN:
186         cvCopyImage(original, img);
187         printf("clear.
");
188         break;
189     }
190 }
191 
192 int main()
193 {
194     img = cvLoadImage( "lena.bmp", 1 );
195 
196     rect = cvRect( -1, -1, 0, 0);
197     
198     // 副本
199     temp = cvCloneImage( img );
200     original = cvCloneImage(img);
201     
202     cvNamedWindow("draw rect");
203     cvSetMouseCallback("draw rect", my_mouse_callback, (void*)img);
204 
205     while(1)
206     {
207         cvCopyImage(img, temp);
208 
209         if(draw_hist)
210         {
211             draw_rect( temp , rect );
212         }
213 
214         cvShowImage( "draw rect", temp);
215 
216         if(cvWaitKey(15) == 27)
217             break;
218     }
219     cvReleaseImage(&img);
220     cvReleaseImage(&temp);
221     cvDestroyAllWindows();
222 
223     return 0;
224 }

运行结果:

不足:在源图像上用鼠标选择矩形区域的时候,无法实时地在图像上反映出来。

原文地址:https://www.cnblogs.com/qdsclove/p/3351188.html