《学习OpenCV》第4章第3题
啊啊啊,超麻烦。
总之还是做出来了。具体看代码吧,不想打字了。
#include "stdafx.h" #include "cv.h" #include "cxcore.h" #include "highgui.h" CvRect box; bool in_drawing = false; int histWidth = 256; int histHeight = 128; int barWidth = 8; IplImage* src = cvLoadImage("D:\\picture\\rena4.jpg"); void MyCallBack(int event, int x, int y, int flags, void* param); IplImage* GetHist(CvHistogram* hist, CvScalar color, int channelNum); void DrawHist(IplImage* img, CvRect rect); void DrawBox(IplImage* img, CvRect rect); int main(int argc, char* argv[]){ assert(src != NULL); IplImage* img = cvCloneImage(src); IplImage* temp = cvCloneImage(src); cvNamedWindow("demo", CV_WINDOW_AUTOSIZE); cvShowImage("demo", img); cvSetMouseCallback("demo", MyCallBack, (void*) img); while (1){ cvCopyImage(src, temp); if (in_drawing) { DrawBox(temp, box); cvShowImage("demo", temp); } else { cvShowImage("demo", img); } char c = cvWaitKey(15); if (c == 27)break; } cvReleaseImage(&temp); cvReleaseImage(&img); cvReleaseImage(&src); cvDestroyWindow("demo"); return 0; } void MyCallBack(int event, int x, int y, int flags, void* param){ IplImage* img = (IplImage*) param; switch (event) { case CV_EVENT_MOUSEMOVE: if (in_drawing == true){ box.width = x - box.x; box.height = y - box.y; } break; case CV_EVENT_LBUTTONDOWN: cvCopyImage(src, img); in_drawing = true; box = cvRect(x, y, 0, 0); break; case CV_EVENT_LBUTTONUP: in_drawing = false; if (box.width < 0){ box.x += box.width; box.width *= -1; } if (box.height < 0){ box.y += box.height; box.height *= -1; } DrawBox(img, box); cvSetImageROI(img, box); cvAddS(img, cvScalar(50, 50, 50), img); cvResetImageROI(img); DrawHist(src, box); break; default: break; } } void DrawHist(IplImage* img, CvRect rect) { assert(img != NULL); cvSetImageROI(img, rect); int dims = 1; //使用一维直方图做每个通道的临时传递直方图 int size = 256; //每一维度bin的数目是256 float range[] = { 0, 255 }; //像素取值范围(矩阵元素取值范围) float* ranges[] = { range }; //制定一个维度的像素值的取值范围 CvHistogram* hist = cvCreateHist(dims, &size, CV_HIST_ARRAY, ranges, 1); cvClearHist(hist); //清空直方图 //给 B、G、R三个通道分配空间 IplImage* imgRed = cvCreateImage(cvGetSize(img), 8, 1); IplImage* imgGreen = cvCreateImage(cvGetSize(img), 8, 1); IplImage* imgBlue = cvCreateImage(cvGetSize(img), 8, 1); //将图像img分解成B G R 三个通道 cvSplit(img, imgBlue, imgGreen, imgRed, NULL); cvResetImageROI(img); cvCalcHist(&imgBlue, hist, 0, 0); // 对B通道计算直方图 IplImage* histBlue = GetHist(hist, cvScalar(255, 0, 0), 0); cvClearHist(hist); cvCalcHist(&imgGreen, hist, 0, 0); // 对G通道计算直方图 IplImage* histGreen = GetHist(hist, cvScalar(0, 255, 0), 1); cvClearHist(hist); cvCalcHist(&imgRed, hist, 0, 0); // 对R通道计算直方图 IplImage* histRed = GetHist(hist, cvScalar(0, 0, 255), 2); IplImage* histImg = cvCreateImage(cvSize(histWidth, histHeight), 8, 3); cvZero(histImg); cvAdd(histBlue, histGreen, histImg); cvAdd(histImg, histRed, histImg); cvNamedWindow("hist"); cvShowImage("hist", histImg); } IplImage* GetHist(CvHistogram* hist, CvScalar color, int channelNum) { //创建图像用于显示直方图 IplImage* imgHist = cvCreateImage(cvSize(histWidth, histHeight), 8, 3); cvZero(imgHist); //获取直方图bin float bin[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; for (int i = 0; i < 8; i++) { for (int j = 0; j < 32; j++){ bin[i] = bin[i] + cvQueryHistValue_1D(hist, i * 32 + j); } } //求bin中的最大值 float max = bin[0]; for (int i = 1; i < 8; i++){ if (max < bin[i]) max = bin[i]; } for (int i = 0; i < 8; i++){ //获取四边形的四个点的坐标 CvPoint pt1 = cvPoint(i * 32 + channelNum*barWidth, histHeight); CvPoint pt2 = cvPoint(i * 32 + (channelNum + 1)*barWidth, histHeight); CvPoint pt3 = cvPoint(i * 32 + (channelNum + 1)*barWidth, histHeight - (bin[i] / max)*histHeight); CvPoint pt4 = cvPoint(i * 32 + channelNum*barWidth, histHeight - (bin[i] / max)*histHeight); int numPts = 5; CvPoint pts[5]; pts[0] = pt1; pts[1] = pt2; pts[2] = pt3; pts[3] = pt4; pts[4] = pt1; //填充四边形 cvFillConvexPoly(imgHist, pts, numPts, color); //填充凸多边形 } return imgHist; } void DrawBox(IplImage* img, CvRect rect) { cvRectangle(img, cvPoint(rect.x, rect.y), cvPoint(rect.x + rect.width, rect.y + rect.height), cvScalar(255, 0, 0) ); }
运行结果如下


浙公网安备 33010602011771号