忙完了期末考试,继续学习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;
}