直方图的均衡、直方图的反向投影算法,opencv鼠标和键盘处理事件

彩色的图像其实是用一个多通道数组来存储的,每个单通道数组中的元素的取值范围都是0255

直方图均衡化可增强图像效果,增加对比度,睫毛头发德国细小物体都要清晰很多。

直方图的反向投影算法。通过鼠标的操作进行截屏,也就是设置兴趣区,用键盘控制兴趣区的平移、放大及缩小,同时将截屏保存下来。

一、灰度直方图均衡:

#include "stdafx.h"
#include"highgui.h"
#include"opencv2/opencv.hpp"
#include"cxcore.h"

#define cvQueryHistValue_1D(hist, idx0) \
 ((float)cvGetReal1D((hist)->bins, (idx0)))


using namespace std;
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")

void FillWhite(IplImage*pImage)
{
 cvRectangle(pImage,cvPoint(0,0),cvPoint(pImage->width,pImage->height),CV_RGB(255,255,255),CV_FILLED);
}
//grayscale histogram 
CvHistogram* CreateGrayImageHist(IplImage** ppImage)
{
 int nHistSize = 256;
 float fRanges[] = { 0, 255 };//range of gray level
 float*pfRanges[] = {fRanges};
 CvHistogram* pcvHistogram = cvCreateHist(1, &nHistSize, CV_HIST_ARRAY, pfRanges);
 cvCalcHist(ppImage,pcvHistogram);
 return pcvHistogram;
}
//create histogram image according to histogram
IplImage* CreateHistogram(int nImageWidth,int nScale, int nImageHeight, CvHistogram* pcvHistogram)
{
 IplImage*pHistImage = cvCreateImage(cvSize(nImageWidth, nImageHeight), IPL_DEPTH_8U,1);
 FillWhite(pHistImage);
 //caculate the max straight square
 float fMaxHistogram = 0;
 cvGetMinMaxHistValue(pcvHistogram,NULL,&fMaxHistogram,NULL,NULL);
 //draw each square value to the map
 int i;
 for ( i = 0; i <nImageWidth; i++)
 {
  float fHistValue = cvQueryHistValue_1D(pcvHistogram,i);//size of the ith pixel
  int nRealHeight = cvRound((fHistValue / fMaxHistogram)*nImageHeight);//the height needed draw
  cvRectangle(pHistImage,cvPoint(i*nScale,nImageHeight-1),cvPoint((i+1)*nScale-1,nImageHeight-nRealHeight),cvScalar(i,0,0,0),CV_FILLED);
 }
 return pHistImage;

}

int main(int argc, char ** argv)
{
 const char * pstrWindowsSrcTitle = "The original Image";
 const char * pstrWindowsGrayTitle = "Gray";
 const char * pstrWindowsHistTitle = "Histogram";
 const char * pstrWindowsGrayEqualizeTitle = "Gray-Equalization";
 const char * pstrWindowsHistEqualizeTitle = "Historag-Equalization";
 IplImage* pSrcImage = cvLoadImage("E:\\图片
\\11.JPG");
 IplImage* pGrayImage = cvCreateImage(cvGetSize(pSrcImage),IPL_DEPTH_8U,1);
 IplImage* pGrayEqualizeImage = cvCreateImage(cvGetSize(pSrcImage),IPL_DEPTH_8U,1);
 cvCvtColor(pSrcImage,pGrayImage,CV_BGR2GRAY);

 int nHistImageWidth = 255;
 int nHistImageHeight = 150;
 int nScale = 2;

 //gray histogram and histogram image
 CvHistogram* pcvHistogram = CreateGrayImageHist(&pGrayEqualizeImage);
 IplImage* pHistImage = CreateHistogram(nHistImageWidth, nScale, nHistImageHeight, pcvHistogram);

 //Equalization
 cvEqualizeHist(pGrayImage,pGrayEqualizeImage);

 //gray histogram and histogram image after equalization
 CvHistogram* pcvHistogramEqualize = CreateGrayImageHist(&pGrayEqualizeImage);
 IplImage* pHistEqualizeImage = CreateHistogram(nHistImageWidth, nScale, nHistImageHeight, pcvHistogramEqualize);
 cvShowImage(pstrWindowsSrcTitle, pSrcImage);
 cvShowImage(pstrWindowsGrayTitle, pGrayImage);
 cvShowImage(pstrWindowsHistTitle, pHistImage);
 cvShowImage(pstrWindowsGrayEqualizeTitle, pGrayEqualizeImage);
 cvShowImage(pstrWindowsHistEqualizeTitle, pHistEqualizeImage);

 cvWaitKey();


}

二、彩色直方图均衡

#include "stdafx.h"
#include"highgui.h"
#include"opencv2/opencv.hpp"
#include"cxcore.h"

#define cvQueryHistValue_1D(hist, idx0) \
 ((float)cvGetReal1D((hist)->bins, (idx0)))


using namespace std;
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")

IplImage* EqualizwHistColorImage(IplImage* pImage)
{
 IplImage* pEquaImage = cvCreateImage(cvGetSize(pImage),pImage->depth,3);
 //equalize the original image after divided into 3 channels , then merge them
 const int MAX_CHANNNEL = 4;
 IplImage* pImageChannel[MAX_CHANNNEL] = {NULL};
 int i;
 for (i = 0; i < pImage->nChannels; i++)
  pImageChannel[i] = cvCreateImage(cvGetSize(pImage), pImage->depth, 1);
  cvSplit(pImage, pImageChannel[0], pImageChannel[1], pImageChannel[2], pImageChannel[3]);
 
 for ( i = 0; i < pImage->nChannels; i++)
  cvEqualizeHist(pImageChannel[i], pImageChannel[i]);
  
 cvMerge(pImageChannel[0], pImageChannel[1], pImageChannel[2], pImageChannel[3], pEquaImage);
 for (i = 0; i < pImage->nChannels; i++)
  cvReleaseImage(&pImageChannel[i]);
 return pEquaImage;
}

 

int main(int argc, char ** argv)
{
 const char * pstrWindowsSrcTitle = "The original Image";
 const char * pstrWindowsHistEqualizeTitle = "Historag-Equalization";

 IplImage* pSrcImage = cvLoadImage("E:\\图片\\11.JPG");
 
 //Equalization
 IplImage* pImageHistogram = NULL;
 pImageHistogram = EqualizwHistColorImage(pSrcImage);
 
 cvShowImage(pstrWindowsSrcTitle, pSrcImage);
 cvShowImage(pstrWindowsHistEqualizeTitle, pImageHistogram);

 cvWaitKey();


}

 

 

直方图的反向投影算法:原理

两张灰度图,其中一张图像尺寸大于等于另一张,其中尺寸较大的图像作为查询图像,另一张为模板图像,直方图反向投影变换的基本原理是:

(1)从尺寸较大的图像的左上角(0,0)开始,切割一块与较小图像尺寸一致的临时图像;
(2)计算临时图像的直方图;
(3)用临时图像的直方图和尺寸较小的图像的直方图对比,对比结果记为c;
(4)直方图对比结果c,就是结果图像(0,0)处的像素值;
(5)逐个像素移动进行图像切割,对比直方图,并记录直方图对比结果;
(6)重复(1)~(5)步直到输入图像的右下角。

需要注意的地方:

(1) 需要在代码实现中加入对图像尺寸大小的判断,如果模版图像尺寸小于查找图像,则程序正常执行,如果等于,这相当于进行直方图比较,如果大于,则应该提示程序无法正常执行

(2)此算法执行效率较低,在使用之前尤其需要注意图像的大小,直方图的维数,对比方式,在计算之前可以考虑对图像进行ColorReduce。

一、灰度直方图反向投影程序

#include "stdafx.h"
#include "opencv2/opencv.hpp"
#include "highgui.h"
using namespace std;




int _tmain(int argc, _TCHAR* argv[])
{
IplImage* src = cvLoadImage("E:\\图片\\1.bmp");
IplImage* src1 = cvLoadImage("E:\\图片\\2.bmp");
int hist_size = 256;
float range[] = {0,255};
float *ranges[] = {range};


IplImage* gray_plan = cvCreateImage(cvGetSize(src),8,1);
cvCvtColor(src,gray_plan,CV_BGR2GRAY);
CvHistogram* Gray_hist = cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1);
cvCalcHist(&gray_plan,Gray_hist,0,0);//calculate histogram automatically
//cvNormalizeHist(Gray_hist,1.0);

IplImage* gray_plan1 = cvCreateImage(cvGetSize(src1), 8, 1);
cvCvtColor(src1, gray_plan1, CV_BGR2GRAY);
IplImage* dst = cvCreateImage(cvGetSize(gray_plan1),IPL_DEPTH_8U,1);
cvCalcBackProject(&gray_plan1,dst,Gray_hist);//reversw projection
cvEqualizeHist(dst,dst);

cvShowImage("first image",src);


cvShowImage("revers image", dst);
cvWaitKey();
return 0;
}

二、彩色直方图反向投影程序

#include "stdafx.h"
#include "opencv2/opencv.hpp"
#include "highgui.h"
using namespace std;


int _tmain(int argc, _TCHAR* argv[])
{
 IplImage* src = cvLoadImage("E:\\图片
\\11.jpg");
 IplImage* src1 = cvLoadImage("E:\\图片
\\11.jpg");
 printf("%f\n", src->origin); //src->origin=0 left-top

 /*cvShowImage("first image", src);*/
 //cvShowImage("second image", src1);
 
 CvRect roi_rect_dst;
 roi_rect_dst.x = 100; roi_rect_dst.y = 100;
 roi_rect_dst.width = 300; roi_rect_dst.height = 300;
 int c = 30, d = 30;
 cvSetImageROI(src1, roi_rect_dst);
 cvShowImage("second image1", src1);
 

 IplImage* gray_plan = cvCreateImage(cvGetSize(src),8,1);
 IplImage* h_plan = cvCreateImage(cvGetSize(src), 8, 1);
 IplImage* s_plan = cvCreateImage(cvGetSize(src), 8, 1);
 IplImage* v_plan = cvCreateImage(cvGetSize(src), 8, 1);
 IplImage* plans[] = { h_plan, s_plan, v_plan };
 IplImage* hsv = cvCreateImage(cvGetSize(src), 8, 3);
 cvCvtColor(src, hsv, CV_BGR2HSV);
 cvSplit(hsv,h_plan,s_plan,v_plan,0);
 printf("h%d\n", h_plan->widthStep);
 printf("s%d\n", s_plan->widthStep);
 printf("v%d\n", v_plan->widthStep);

 IplImage* gray_plan1 = cvCreateImage(cvGetSize(src1), 8, 1);
 IplImage* h_plan1 = cvCreateImage(cvGetSize(src1), 8, 1);
 IplImage* s_plan1 = cvCreateImage(cvGetSize(src1), 8, 1);
 IplImage* v_plan1 = cvCreateImage(cvGetSize(src1), 8, 1);
 IplImage* plans1[] = { h_plan1, s_plan1, v_plan1};
 IplImage* hsv1 = cvCreateImage(cvGetSize(src1), 8, 3);
 cvCvtColor(src1, hsv1, CV_BGR2HSV);
 cvSplit(hsv1, h_plan1, s_plan1, v_plan1, 0);
 printf("h%d\n", h_plan1->widthStep);
 printf("s%d\n", s_plan1->widthStep);
 printf("v%d\n", v_plan1->widthStep);


 int h_bins = 20, s_bins = 20, v_bins = 20;
 int hist_size[] = {h_bins,s_bins,v_bins};
 float h_ranges[] = {0,255};
 float s_ranges[] = { 0, 255 };
 float v_ranges[] = { 0, 255 };
 float*ranges[] = {h_ranges,s_ranges,v_ranges};
 CvHistogram* hist;
 hist = cvCreateHist(3,hist_size,CV_HIST_ARRAY,ranges,1);
 cvCalcHist(plans1,hist,0,0);
 IplImage* back_project = cvCreateImage(cvGetSize(src),8,1);
 cvZero(back_project);
 //cvNormalizeHist(Gray_hist,1.0);

 cvCalcBackProject(plans,back_project,hist);//reversw projection
 cvShowImage("first image",src);
 cvShowImage("revers image", back_project);
 cvWaitKey();
 return 0;
}

三、鼠标点击事件 

#include "stdafx.h"
#include"highgui.h"
#include"opencv2/opencv.hpp"
#include"cxcore.h"
using namespace std;

void my_mouse_callback(
    int Event, int x, int y, int flags, void *param
);
CvRect box;
bool drawing_box = false;
void draw_box(IplImage *img, CvRect rect){
    // cvRectangle 会修改img的数据 
    cvRectangle(
        img,
       cvPoint(box.x, box.y),
         cvPoint(box.x + box.width, box.y + box.height),
          cvScalar(0xff, 0xff, 0x00)
  );
 
}
int main(int argc, char ** argv)
{
     box = cvRect(-1, -1, 0, 0);
     IplImage* img = cvCreateImage(
          cvSize(200, 200),
          IPL_DEPTH_8U,
        3
 );
     cvZero(img);
     // 函数 cvCloneImage 制作图像的完整拷贝包括头、ROI和数据 
   IplImage * temp = cvCloneImage(img);
 
    cvNamedWindow("Box Example");

    cvSetMouseCallback(
         "Box Example",
         my_mouse_callback,
        (void *)img
 );
   while (1){
         // 把 img的所有 复制给 temp, temp 是img 此时的一个副本 
           // draw_box(temp, box), 由于此时是鼠标移动的时候,所以最终的rect还 
           // 没有确定,说以不能把temp 该成img, 如果改成img, 那么每隔15ms 
           // img的数据就会跟新一次,同样,cvshowimage中的一定要为现在的temp 
    temp=cvCloneImage(img);// img -> temp 
         // 回调函数修改的是img 
           if (drawing_box)
               draw_box(temp, box);
          cvShowImage("Box Example", temp);
          if (cvWaitKey(15) == 27) break;
  
 }
     cvReleaseImage(&img);
     cvReleaseImage(&temp);
     cvDestroyWindow("Box Example");
 }
void my_mouse_callback(int Event, int x, int y, int flags, void *param){
 
     IplImage* curImg = (IplImage *)param;
     switch (Event){
          case CV_EVENT_MOUSEMOVE:{
               if (drawing_box){
                   box.width = x - box.x;
                    box.height = y - box.y;
    
   }
           }
          break;
    case CV_EVENT_LBUTTONDOWN:{
               drawing_box = true;
               box = cvRect(x, y, 0, 0);
          }
          break;
    case CV_EVENT_LBUTTONUP:{
              drawing_box = false;
               draw_box(curImg, box);
           }
          break;
  
 }
 
}

 四、鼠标和键盘处理事件

 

#include "stdafx.h"
#include"highgui.h"
#include"opencv2/opencv.hpp"
#include"cxcore.h"
using namespace std;
using namespace cv;
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")


CvPoint pt1 = Point(0, 0);
CvPoint pt2 = Point(0, 0);
bool is_selecting = false;

void cvMouseCallback(int mouseEvent, int x, int y, int flags, void* param)
{
 switch(mouseEvent)
 {
  case CV_EVENT_LBUTTONDOWN:
   pt1 = Point(x, y);
   pt2 = Point(x, y);
   is_selecting = true;
   break;
  case CV_EVENT_MOUSEMOVE:
   if (is_selecting)
    pt2 = Point(x,y);
   break;
  case CV_EVENT_LBUTTONUP:
   pt2 = Point(x,y);
   is_selecting = false;
   break;
 }
 return;
}


int main(int argc, char ** argv)
{
 CvRect rect = cvRect(pt1.x, pt1.y, abs(pt2.x - pt1.x), abs(pt2.y - pt1.y));
 IplImage* pSrcImage = cvLoadImage("E:\\图片\\11.JPG");
 IplImage* Img1;
 cvNamedWindow("IMG",0);
 cvSetMouseCallback("IMG",cvMouseCallback);
 //Equalization
 bool SHIFTER_ON = false;
 while (true)
 {
  Img1 = cvCloneImage(pSrcImage);
  cvRectangle(Img1, pt1, pt2, cvScalar(255, 255, 255));
  cvShowImage("IMG", pSrcImage);
  cvShowImage("IM1G", Img1);
  char key = cvWaitKey(10);
  switch (key)
  {
  case'\t':
   SHIFTER_ON = !SHIFTER_ON; break;
  case 'a':
   pt1.x--; pt2.x--; break;
  case 's':
   pt1.y++; pt2.y++; break;
  case 'd':
   pt1.x++; pt2.x++; break;
  case 'w':
   pt1.y--; pt2.y--; break;

   //AMPLIFICATION AND narrow ROI,the mainly operation is shifteration for ege of initial ROI
  case '1':
   if (SHIFTER_ON) pt1.x--;
   else pt2.x--;
   break;
  case '2':
   if (SHIFTER_ON) pt2.y++;
   else pt1.y++;
   break;
  case '3':
   if (SHIFTER_ON) pt2.x++;
   else pt1.x++;
   break;
  case '4':
   if (SHIFTER_ON) pt1.y--;
   else pt2.y--;
   break;
   

  case '\r':
   cvSetImageROI(Img1, rect);
   break;
   cvSaveImage("e:\\879,jpg", Img1);
   
  }
  if (key == 27) break;
 }
 cvReleaseImage(&pSrcImage);
 cvReleaseImage(&Img1);
  return 0;
 }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值