忙完了期末考试,继续学习opencv~
这题考察了很多知识,知识点在我前面的练习中都有讲解。主要思路就是将三通道图分成单通道单个处理,最后将三个图拼在一起显示。
这题考察了很多知识,知识点在我前面的练习中都有讲解。主要思路就是将三通道图分成单通道单个处理,最后将三个图拼在一起显示。
在释放内存的时候要细心,我总是在上面栽跟头,多调试调试吧!
#include "stdafx.h" #include<highgui.h> #include<cv.h> #include<stdlib.h> CvRect g_rect; bool g_isdown; bool g_window;//未点击之前不弹出对选中区域图像 IplImage* selec_imag = NULL;//选中区域图像 void my_callback(int event, int x, int y, int flags, void* param) { IplImage* image = (IplImage*)param; switch (event) { case CV_EVENT_LBUTTONDOWN: g_rect.x = x; g_rect.y = y; break; case CV_EVENT_LBUTTONUP: { if (x > g_rect.x) { g_rect.width = x - g_rect.x; g_rect.height = y - g_rect.y; } else //如果鼠标移动方向由下往上 { g_rect.width = g_rect.x - x; g_rect.height = g_rect.y - y; g_rect.x = x; g_rect.y = y; } cvSetImageROI(image, g_rect);//选中矩形区域 selec_imag = cvCreateImage(cvSize(g_rect.width, g_rect.height), image->depth, image->nChannels); cvCopyImage(image, selec_imag); cvResetImageROI(image); g_isdown = TRUE; g_window = TRUE; break; } } } void high_light(IplImage* image, CvRect rect) //对选中区域高亮 { assert(image != NULL); int row, col; for (row = rect.y; row < rect.y + rect.height; row++) { uchar* ptr = (uchar*)(image->imageData + row*image->widthStep); for (col = rect.x; col < rect.x + rect.width; col++) { ptr[col * 3 + 0] = 60;//B ptr[col * 3 + 1] = 194;//G ptr[col * 3 + 2] = 21;//R } } } IplImage* histcal(IplImage* sin_image, CvScalar& color)//具体创建直方图的函数 { int dims = 1; int size[] = { 256 }; float range[] = { 0, 255 }; float* ranges[] = { range }; CvHistogram* hist = cvCreateHist(dims, size, CV_HIST_ARRAY, ranges, 1);//创建直方图 cvCalcHist(&sin_image, hist, 0, 0);//计算图片的像素分布保存在直方图中 IplImage* show = cvCreateImage(cvSize(256, 256), 8, 3);//创建显示直方图的图像 cvSet(show, cvScalar(255, 255, 255));//使图片背景为白色 float max_value = 0; cvGetMinMaxHistValue(hist, 0, &max_value, 0, 0);//找出图片中最多像素值的个数 float max = 256 * 0.9;//定义直方图最高高度不超过图片的90% for (int i = 0; i < 256; i++) { float* value = cvGetHistValue_1D(hist, i);//获取某一区间的像素值 CvPoint p0 = cvPoint(i, 256);//接下来创建两个点,画矩形 float out = 256 - (*value)*max / max_value; CvPoint p1 = cvPoint(i + 1, out); cvRectangle(show, p0, p1, color, 1, 8, 0); } return show; } IplImage* statistic(IplImage* image)//显示直方图的函数 { IplImage* B_image = cvCreateImage(cvGetSize(image), image->depth, 1); IplImage* G_image = cvCreateImage(cvGetSize(image), image->depth, 1); IplImage* R_image = cvCreateImage(cvGetSize(image), image->depth, 1); cvSplit(image, B_image, G_image, R_image,NULL); IplImage* blue = histcal(B_image, cvScalar(0, 0, 255)); IplImage* green = histcal(G_image, cvScalar(0, 255, 0)); IplImage* red = histcal(R_image, cvScalar(255, 0, 0)); IplImage* all = cvCreateImage(cvSize(blue->width*2, blue->height*2), 8, 3); cvSet(all, cvScalar(255, 255, 255)); cvSetImageROI(all, cvRect(0, 0, blue->width, blue->height)); cvCopy(blue, all); cvResetImageROI(all); cvSetImageROI(all, cvRect(blue->width, 0, blue->width, blue->height)); cvCopy(red, all); cvResetImageROI(all); cvSetImageROI(all, cvRect(0, blue->width, blue->width, blue->height)); cvCopy(green, all); cvResetImageROI(all); cvReleaseImage(&B_image); cvReleaseImage(&G_image); cvReleaseImage(&R_image); cvReleaseImage(&blue); cvReleaseImage(&green); cvReleaseImage(&red); cvReleaseImage(&image); return all; } int _tmain(int argc, _TCHAR* argv[]) { IplImage* image = cvLoadImage("D:/3.jpg"); assert(image != NULL); cvNamedWindow("window"); if (g_window) { cvNamedWindow("select", 0); g_window = FALSE; } cvSetMouseCallback("window", my_callback, (void*)image); IplImage* temp = cvCloneImage(image); while (1) { cvShowImage("window", temp); if (g_isdown) { temp = cvCloneImage(image); high_light(temp, g_rect); cvShowImage("window", temp); cvReleaseImage(&temp);//必须释放内存,因为clone一次就开辟一块空间 cvShowImage("select", selec_imag); IplImage* temp1 = statistic(selec_imag); cvShowImage("show", temp1); cvReleaseImage(&temp1);//临时内存要释放掉 g_isdown = FALSE; } char c = cvWaitKey(30); if (c == 27) break; } //最后释放的时候要注意,前面释放过的不能重复释放野指针 cvReleaseImage(&image); cvReleaseImage(&temp); cvDestroyAllWindows(); return 0; }