示例程序039--反向投影

什么是反向投影:

简单的说:用输入图像的某一位置上像素值(多维或灰度)对应在直方图的一个bin上的值来代替该像素值,所以得到的反向投影图是单通的。用统计学术语,输出图像象素点的值是观测数组在某个分布(直方图)下的概率。(参考自:http://blog.163.com/thomaskjh@126/blog/static/370829982010112810358501/

应用举例:如果有一个肤色直方图,你可以用它来寻找其他图像中的肤色区域。

 

工作原理:

以下面的图片为例:

1.首先要获得模型图片的肤色直方图,比如下图:

示例程序039--反向投影左边是模型图,右边是H-S二维直方图

 

2.下面是测试图片及其H-S二维直方图
示例程序039--反向投影

 

接下来要做的事情就是,举个例子:

例如灰度图像如下

Image=

  0    1    2    3

  4    5    6    7

  8    9   10   11

  8    9   14   15

 

该灰度图的直方图为(bin指定的区间为[0,3)[4,7)[8,11)[12,16)

Histogram=

  4    4    6    2

(3)反向投影图

Back_Projection=

  4    4    4    4

  4    4    4    4

  6    6    6    6

  6    6    2    2

例如位置(0,0)上的像素值为0,对应的bin[0,3),所以反向直方图在该位置上的值这个bin的值4

 

用到的函数:

calcBackProject

calcBackProject的输入为图像及其直方图,输出与待跟踪图像大小相同,每一个像素点表示该点为目标区域的概率。这个点越亮,该点属于物体的概率越大。

 

程序代码及注释:

(该代码是最简单的一维直方图,且模型图片也是本身,下回再研究如何用floodFill定义图片肤色区域的掩码,而不是整个图片的直方图,二维直方图已经在上一篇文章中实现)

// 047 反向投影.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include<iostream>
using namespace std;
using namespace cv;


/// 全局变量
Mat src; Mat hsv; Mat hue;
int bins = 25;

 

void Hist_and_Backproj(int, void* );


int _tmain(int argc, _TCHAR* argv[])
{
  src=imread("hand_sample2.jpg");

 

  /// 转换到 HSV 空间
  cvtColor( src, hsv, CV_BGR2HSV );

 

  /// 分离 Hue 通道,mixChannels参数详细解释如下:
//&hsv: 输入图像的矩阵, 被拷贝的通道的来源
//1: 输入数组中图像的数目
//&hue: 目的图像的矩阵, 储存拷贝的通道
//1: 目的数组中图像的数目
//ch[] = {0,0}: 通道索引对的数组,指示如何将输入图像的某一通道拷贝到目的图像的某一通道。
//在这里,&hsv图像的0通道(即Hue通道)被拷贝到&hue图像(单通道)的0 通道。
//1: 通道索引对的数目
  hue.create( hsv.size(), hsv.depth() );          //创建单通道hue图像
  int ch[] = { 0, 0 };
  mixChannels( &hsv, 1, &hue, 1, ch, 1 );

  /// 创建 Trackbar 来输入bin的数目
  char* window_image = "Source image";
  createTrackbar("* Hue  bins: ", window_image, &bins, 180, Hist_and_Backproj );
 
  Hist_and_Backproj(0, 0);//用于第一次没有滑动滚动条的显示

 
  namedWindow( window_image, CV_WINDOW_AUTOSIZE );
  imshow( window_image, src );

 
 


 

 waitKey(0);
 return 0;
}


//回调函数
void Hist_and_Backproj(int, void* )
{
  MatND hist;
  int histSize = MAX( bins, 2 );
  float hue_range[] = { 0, 180 };
  const float* ranges = { hue_range };

 

  /// 计算直方图并归一化
  calcHist( &hue, 1, 0, Mat(), hist, 1, &histSize, &ranges, true, false );
  normalize( hist, hist, 0, 255, NORM_MINMAX, -1, Mat() );

 

  /// 计算反向投影
  MatND backproj;
  calcBackProject( &hue, 1, 0, hist, backproj, &ranges, 1, true );

 

  /// 显示反向投影
  imshow( "BackProj", backproj );

 

  /// 显示直方图
  int w = 400; int h = 400;
  int bin_w = cvRound( (double) w / histSize );
  Mat histImg = Mat::zeros( w, h, CV_8UC3 );

  for( int i = 0; i < bins; i ++ )
     { rectangle( histImg, Point( i*bin_w, h ), Point( (i+1)*bin_w, h - cvRound( hist.at<float>(i)*h/255.0 ) ), Scalar( 0, 0, 255 ), -1 ); }

  imshow( "Histogram", histImg );
}

运行结果:

 

示例程序039--反向投影
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值