《学习opencv》第四章第三题(全)

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


猜你喜欢

转载自blog.csdn.net/qq_24282081/article/details/73864928