《学习OpenCV》第四章课后题3-b
2015-07-19 17:59
197 查看
题目说明:
在一个独立的窗口中,使用画图函数画一个图表,分别用蓝、绿和红色表示选中区域中每种颜色的像素数量。这是选定区域的颜色直方图。x坐标系表示像素值范围在0-31,32-63,…,223,255;y坐标表示在选定区域中对应像素的数量。对每一个颜色通道(BGR)都进行统计。
注:qdsclove的问题已解决,解决办法参考LJH0600301217的专栏,但是“LJH0600301217的专栏”的代码运行时会造成内存泄露,更正办法在绘直方图函数后添加语句b_hist = false。
引用:LJH0600301217的专栏、qdsclove
/article/1945403.html
/article/5776309.html
在一个独立的窗口中,使用画图函数画一个图表,分别用蓝、绿和红色表示选中区域中每种颜色的像素数量。这是选定区域的颜色直方图。x坐标系表示像素值范围在0-31,32-63,…,223,255;y坐标表示在选定区域中对应像素的数量。对每一个颜色通道(BGR)都进行统计。
#include "cv.h" #include "highgui.h" //鼠标回调函数 void my_mouse_callback(int event,int x, int y, int flag, void* param); CvRect box = cvRect(0,0,0,0); bool draw_box = false; bool high_light = false; bool b_hist = false; // 直方图尺寸 CvSize image_size = cvSize( 256, 300); //画矩形 void drawbox(IplImage* img, CvRect rect) { cvRectangle(img,cvPoint(rect.x, rect.y),cvPoint(rect.x + rect.width, rect.y+rect.height),cvScalar(0,0,0)); } //高亮矩形框的内容 void highlight(IplImage* img, CvRect rect) { if (high_light == true) { for (int y = rect.y; y<rect.y + rect.height; y++) { uchar* ptr = (uchar*)(img->imageData+y*img->widthStep); for (int x = rect.x; x<rect.x + rect.width; x++) { ptr[x*img->nChannels + 1] = 150; ptr[x*img->nChannels + 2] = 110; } } } cvShowImage("Box",img); } //画各个单通道图像直方图 IplImage * draw_single_hist(IplImage* img,CvScalar value) { int size = 256; float range[] = {0, 255}; float* ranges[] = {range}; // 创建直方图 CvHistogram * hist = cvCreateHist( 1, &size, CV_HIST_ARRAY, ranges, 1); cvCalcHist( &img, hist, 0, NULL ); float max_value = 0; cvGetMinMaxHistValue( hist, NULL, &max_value, NULL, NULL ); // 新建一幅3通道的图像 IplImage* dst = cvCreateImage(image_size, IPL_DEPTH_8U, 3 ); cvSet( dst, cvScalarAll(255) ); double bin_width = (double)dst->width/256; double bin_unith = (double)dst->height/max_value; // 高度比例 for(int i = 0; i < 256; i++) { // 获得矩形左上角和右下角坐标 CvPoint p0 = cvPoint( i + bin_width, dst->height ); CvPoint p1 = cvPoint( (i+1) * bin_width, dst->height - cvGetReal1D(hist->bins, i) * bin_unith ); // 画实心矩形 cvRectangle( dst, p0, p1, value, -1, 8, 0 ); } return dst; } //画直方图 void draw_hist(IplImage* img, CvRect rect) { // 设置感兴趣区域 cvSetImageROI( img, rect); // 为感兴趣区分配空间 IplImage* src_rect = cvCreateImage ( cvSize( rect.width, rect.height ), img->depth, img->nChannels ); // 复制感兴趣数据 cvCopy(img, src_rect ); // 取消设置感兴趣区 cvResetImageROI( img ); // 为单色通道图像分配空间 IplImage* r_img = cvCreateImage( cvGetSize( src_rect),src_rect->depth, 1 ); IplImage* g_img = cvCreateImage( cvGetSize( src_rect),src_rect->depth, 1 ); IplImage* b_img = cvCreateImage( cvGetSize( src_rect),src_rect->depth, 1 ); IplImage* gray_img = cvCreateImage( cvGetSize( src_rect),src_rect->depth, 1 ); // 分离RGB分量 cvSplit( src_rect, r_img, g_img, b_img, NULL); // 灰度转换 cvCvtColor( src_rect, gray_img, CV_BGR2GRAY); // 显示每个通道的图像 cvNamedWindow("red",0); cvNamedWindow("blue",0); cvNamedWindow("green",0); cvShowImage( "red", r_img); cvShowImage( "blue", g_img); cvShowImage( "green", b_img); //画每个通道的直方图 IplImage* r_hist = draw_single_hist(r_img,cvScalar(0x00, 0x00, 0xff)); IplImage* g_hist = draw_single_hist(g_img,cvScalar(0x00, 0xff, 0x00)); IplImage* b_hist = draw_single_hist(b_img,cvScalar(0xff, 0x00, 0x00)); IplImage* gray_hist = draw_single_hist(gray_img,cvScalar(0x00, 0x00, 0x00)); // 把四个直方图在一幅图片上显示出来 IplImage* dst = cvCreateImage( cvSize( image_size.width * 2, image_size.height * 2), 8, 3 ); cvSetZero( dst ); // 拷贝红色分量直方图 CvRect r_rect = cvRect( 0, 0, image_size.width, image_size.height); cvSetImageROI(dst, r_rect); cvCopy( r_hist, dst); // 拷贝绿色分量直方图 CvRect g_rect = cvRect(image_size.width, 0, image_size.width, image_size.height ); cvSetImageROI( dst, g_rect); cvCopy( g_hist, dst); // 拷贝蓝色分量直方图 CvRect b_rect = cvRect(0, image_size.height, image_size.width, image_size.height ); cvSetImageROI(dst, b_rect); cvCopy( b_hist, dst ); // 拷贝灰色分量直方图 CvRect gray_rect = cvRect( image_size.width, image_size.height, image_size.width, image_size.height ); cvSetImageROI( dst, gray_rect); cvCopy( gray_hist, dst); cvResetImageROI( dst ); //显示最终的图像 cvNamedWindow("hist_rgb",0); cvShowImage( "hist_rgb", dst); } int main(int argc, char** argv) { IplImage* image = cvLoadImage("E:/shark.jpg"); assert(image != NULL); //保留一个原图的副本,便于后续回复原始数据 IplImage* copyImage = cvCreateImage(cvGetSize(image),image->depth,image->nChannels); cvCopy(image,copyImage); cvNamedWindow("Box",CV_WINDOW_AUTOSIZE); cvShowImage("Box", copyImage); //注册鼠标事件 cvSetMouseCallback("Box",my_mouse_callback,(void*)copyImage); while (1) { //一定要在这里,画图是画在图像的副本上。否则,画出的图是连着的 cvCopy(image,copyImage); if (draw_box == true) { drawbox(copyImage,box); cvShowImage("Box", copyImage); } if (high_light == true) { highlight(copyImage, box); } if (b_hist == true) { draw_hist(image,box); b_hist = false;//要加上这句,要不循环会使内存泄露 } if (cvWaitKey(15) == 27) break; } return 0; } void my_mouse_callback(int event,int x, int y, int flag, void* param) { IplImage* image = (IplImage*) param; switch (event) { case CV_EVENT_LBUTTONDOWN: high_light = false; draw_box = true; b_hist = false; box = cvRect(x,y,0,0); break; case CV_EVENT_MOUSEMOVE: if (draw_box == true) { box.width = x - box.x; box.height = y - box.y; } break; case CV_EVENT_LBUTTONUP: draw_box = false; high_light = true; b_hist =true; if(box.width < 0) { box.x += box.width; box.width *= -1; } if(box.height < 0) { box.y += box.height; box.height *= -1; } break; } }
注:qdsclove的问题已解决,解决办法参考LJH0600301217的专栏,但是“LJH0600301217的专栏”的代码运行时会造成内存泄露,更正办法在绘直方图函数后添加语句b_hist = false。
引用:LJH0600301217的专栏、qdsclove
/article/1945403.html
/article/5776309.html
相关文章推荐
- Linux -gdb如何显示宏定义的值
- 伪装隐藏Nginx,PHP版本号提升服务器安全性
- Linux环境下段错误的产生原因及调试方法小结
- Linux下的GitHub安装与简单配置教程
- Tachyon0.6.4+Spark1.3+hadoop2.6.0 配置教程详解
- spark1.4.0基于yarn的安装心得体会
- VMWare10下基于Ubuntu14搭建Hadoop-1.2.1集群
- Linux下变量配置规则
- Linux软件安装
- 【安卓基础一】安卓架构、Dalvik VM、apk与.dex
- HADOOP之HDFS
- Cookie-网站登录-下次自动登录
- Linux下安装java
- opensuse如何打开终端快捷键
- Linux学习与总结:6-Linux应用程序安装部署
- Linux进程间通信
- !!运维博客
- !!运维博客
- Linux内存寻址之一:内存地址分类以及MMU介绍(转)
- Linux内核态与用户态通信的常用方法