《学习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)
        );
}

 

运行结果如下

posted @ 2013-12-19 22:01  sixfancy  阅读(240)  评论(0)    收藏  举报