OpenCV 反向投影, 基于块的反向投影 和 模板匹配

/*
 *用反向投影, 基于块的反向投影 和 模板匹配寻找目标物体
 *1)要可视化反向投影结果,则不能用归一化直方图, 因为结果图像中的值就是hist相应bin的值
 *2)匹配结果很好,但是计算时间太长! 不能接受
 *3) 注意三个函数处理后的结果图像的大小和位数. back_project的结果图必须是8bit,不能是32; block反向投影的结果图必须是浮点; 模板比配的结果图,8bit 或者浮点都可以; 
 *4) 注意不同比配方法得到的值解释不同;如CHISQR方法中最小值为最佳匹配; CCOEFF方法,最大值表示最佳匹配 
 *
 * Date: 2012/4/2 
 * Author: Rocky Chen
 */
#include "stdio.h"
#include "stdafx.h"
#include "highgui.h"
#include <cv.h>
#include <cxcore.h>
#include <ctype.h>
#include "iostream"
#include "math.h"


using namespace std;
using namespace cv;
  
int main(int argc, char** argv)  
{  
//窗口,图像文件初始化
const char* img_file = "C:\\Users\\Administrator\\Pictures\\张辛苑\\1.jpg";
// const char* model_file = "C:\\Users\\Administrator\\Pictures\\张辛苑\\histmodel.jpg";
// const char* model_file = "C:\\Users\\Administrator\\Pictures\\张辛苑\\histmodel2.jpg";  
const char* model_file = "C:\\Users\\Administrator\\Pictures\\张辛苑\\histmodel3.jpg";


const char* wd_imgsrc = "原图像";
const char* wd_model_hist = "模板的HS直方图";
const char* wd_template = "模板匹配结果";
const char* wd_backpro = "反向投影匹配结果";
const char* wd_block_backpro = "block反向投影匹配结果";


cvNamedWindow(wd_imgsrc);
cvNamedWindow(wd_model_hist);
cvNamedWindow(wd_template);
cvNamedWindow(wd_backpro);
cvNamedWindow(wd_block_backpro);


//载入图像
IplImage* imgsrc = cvLoadImage(img_file);
assert( imgsrc != NULL);
IplImage* imgmodel = cvLoadImage(model_file);
assert( imgmodel != NULL);


//创建处理后的结果图像
IplImage* img_template = cvCreateImage(cvSize(imgsrc->width - imgmodel->width + 1, imgsrc->height - imgmodel->height + 1), 32, 1); //模板匹配结果图像
IplImage* img_backpro = cvCreateImage(cvGetSize(imgsrc), 8, 1); //反向投影结果图,必须是8bit图像,不能是32bit
CvSize patch_size = cvGetSize(imgmodel);  //block大小
IplImage* img_block_backpro = cvCreateImage(cvGetSize(img_template), IPL_DEPTH_32F, 1); //block反向投影结果图


//建立imgsrc 和 img model 的单通道图像数组
IplImage* model_hsv = cvCreateImage(cvGetSize(imgmodel), 8 , 3);   //计算要匹配模板的HS直方图
cvCvtColor(imgmodel, model_hsv, CV_BGR2HSV);    //生成 hsv图像
IplImage* h_plane =  cvCreateImage(cvGetSize(imgmodel), 8 , 1); 
IplImage* s_plane =  cvCreateImage(cvGetSize(imgmodel), 8 , 1); 
IplImage* v_plane =  cvCreateImage(cvGetSize(imgmodel), 8 , 1); 
IplImage* planes[] = {h_plane, s_plane}; //计算直方图cvCalcHist()的参数 IplImage**
cvSplit(model_hsv, h_plane, s_plane, v_plane, NULL);  // cvSplit() = cvCvtPixToPlane()


IplImage* imgsrc_hsv = cvCreateImage(cvGetSize(imgsrc), 8 , 3);   //计算要匹配模板的HS直方图
cvCvtColor(imgsrc, imgsrc_hsv, CV_BGR2HSV);    //生成 hsv图像
IplImage* src_h_plane =  cvCreateImage(cvGetSize(imgsrc), 8 , 1); 
IplImage* src_s_plane =  cvCreateImage(cvGetSize(imgsrc), 8 , 1); 
IplImage* src_v_plane =  cvCreateImage(cvGetSize(imgsrc), 8 , 1); 
IplImage* imgsrc_planes[] = {src_h_plane, src_s_plane}; //计算直方图cvCalcHist()的参数 IplImage**
cvSplit(imgsrc_hsv, src_h_plane, src_s_plane, src_v_plane, NULL);  // cvSplit() = cvCvtPixToPlane()

//计算model的HS直方图
int h_bins = 30;
int s_bins = 32;
CvHistogram *model_hist, *model_hist_normalized;
int hist_size[] = {h_bins, s_bins};  //直方图大小 = h_bins * s_bins
float h_ranges[] = {0, 180};  //均匀bin, range只需要最大最小边界
float s_ranges[] = {0,255};
float* ranges[] = {h_ranges, s_ranges};
model_hist = cvCreateHist(2,
hist_size,
CV_HIST_ARRAY,
ranges,
1);   //"1" 表示bin均匀.
model_hist_normalized = cvCreateHist(2,   //归一化直方图
hist_size,
CV_HIST_ARRAY,
ranges,
1);   //"1" 表示bin均匀.


cvCalcHist(planes, model_hist, 0, 0);   //得到匹配模板的HS直方图
    cvCopyHist(model_hist, &model_hist_normalized);
cvNormalizeHist( model_hist_normalized, 1.0); //归一化.


//显示匹配模板的HS直方图
int scale =10;
IplImage* model_hist_img = cvCreateImage( cvSize(h_bins * scale, s_bins * scale), 8, 3); 
cvZero( model_hist_img);

float max_value = 0;
cvGetMinMaxHistValue( model_hist, 0, &max_value, 0, 0);

for( int h = 0; h< h_bins; h++)
for( int s = 0; s< s_bins; s++)
{
float bin_val = cvQueryHistValue_2D( model_hist, h, s);
int intensity = cvRound(bin_val * 255/ max_value); //cvRound, cvFloor, cvCeil 用一种舍入方法将输入浮点数转换成整数. 
     //cvRound 返回和参数最接近的整数值.
 //直方图归一化不影响归一化颜色值后直方图的显示
cvRectangle( model_hist_img, 
 cvPoint(h*scale, s* scale),
 cvPoint((h+1)*scale-1, (s+1)*scale -1),
 CV_RGB(intensity, intensity, intensity),  //rgb值相等时,呈现的是明亮的灰度
 CV_FILLED
 );
}



//反向投影,block反向投影,template匹配
cvCalcBackProject(imgsrc_planes, img_backpro, model_hist);  //要可视化反向投影结果,则不能用归一化直方图, 因为结果图像中的值就是hist相应bin的值
cvCalcBackProjectPatch( imgsrc_planes, img_block_backpro, patch_size, model_hist_normalized, CV_COMP_CHISQR, 1);  //CHISQR方法中,低分匹配度高
cvMatchTemplate( imgsrc, imgmodel, img_template, CV_TM_CCOEFF_NORMED); //CCOEFF方法,最大值表示最佳匹配

//用cvMinMaxLoc() 找到block反向投影和模板匹配中的最佳匹配位置,并处标记圆形
CvPoint min_loc_block, max_loc_templ;
    cvMinMaxLoc(img_block_backpro, 0, 0, &min_loc_block, 0, 0);  //block反向投影,CHISQR的最小值的位置
cvMinMaxLoc(img_template, 0, 0, 0, &max_loc_templ, 0);
//标记极值点
    cvCircle(img_block_backpro, min_loc_block, 30, CV_RGB(0,0,0));  //画黑色的圆
cvCircle(img_template, max_loc_templ, 30, CV_RGB(255,255,255));  //画白色的圆
cvCircle(imgsrc,   //在原图像中标记找到的目标物体
cvPoint(max_loc_templ.x + patch_size.width /2, max_loc_templ.y + patch_size.height/2),   //目标点再原图像中的位置
40,
CV_RGB(0,255,0)
);


cvShowImage(wd_imgsrc, imgsrc);
cvShowImage(wd_model_hist, model_hist_img);
cvShowImage(wd_template, img_template);
cvShowImage(wd_backpro, img_backpro);
cvShowImage(wd_block_backpro, img_block_backpro);
cvWaitKey();


cvReleaseImage(&imgsrc);
cvReleaseImage(&model_hist_img);
    cvDestroyAllWindows();  
 
return 0;  
}  
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值