http://docs.opencv.org/doc/tutorials/imgproc/histograms/back_projection/back_projection.html?highlight=normalize

http://docs.opencv.org/modules/core/doc/operations_on_arrays.html?highlight=normalize#void%20normalize%28InputArray%20src,%20OutputArray%20dst,%20double%20alpha,%20double%20beta,%20int%20norm_type,%20int%20dtype,%20InputArray%20mask%29

In this tutorial you will learn:

  • What is Back Projection and why it is useful
  • How to use the OpenCV function calcBackProject to calculate Back Projection
  • How to mix different channels of an image by using the OpenCV function mixChannels

Theory

What is Back Projection?

  • Back Projection is a way of recording how well the pixels of a given image fit the distribution of pixels in a histogram model.
  • To make it simpler: For Back Projection, you calculate the histogram model of a feature and then use it to find this feature in an image.
  • Application example: If you have a histogram of flesh color (say, a Hue-Saturation histogram ), then you can use it to find flesh color areas in an image:

How does it work?

  • We explain this by using the skin example:

  • Let’s say you have gotten a skin histogram (Hue-Saturation) based on the image below. The histogram besides is going to be our model histogram (which we know represents a sample of skin tonality). You applied some mask to capture only the histogram of the skin area:

  • Now, let’s imagine that you get another hand image (Test Image) like the one below: (with its respective histogram):

  • What we want to do is to use our model histogram (that we know represents a skin tonality) to detect skin areas in our Test Image. Here are the steps

    1. In each pixel of our Test Image (i.e. ), collect the data and find the correspondent bin location for that pixel (i.e. ).

    2. Lookup the model histogram in the correspondent bin - - and read the bin value.

    3. Store this bin value in a new image (BackProjection). Also, you may consider to normalize the model histogram first, so the output for the Test Image can be visible for you.

    4. Applying the steps above, we get the following BackProjection image for our Test Image:

    5. In terms of statistics, the values stored in BackProjection represent the probability that a pixel in Test Image belongs to a skin area, based on the model histogram that we use. For instance in our Test image, the brighter areas are more probable to be skin area (as they actually are), whereas the darker areas have less probability (notice that these “dark” areas belong to surfaces that have some shadow on it, which in turns affects the detection).

Code

  • What does this program do?

    • Loads an image
    • Convert the original to HSV format and separate only Hue channel to be used for the Histogram (using the OpenCV function mixChannels)
    • Let the user to enter the number of bins to be used in the calculation of the histogram.
    • Calculate the histogram (and update it if the bins change) and the backprojection of the same image.
    • Display the backprojection and the histogram in windows.
  • Downloadable code:

    1. Click here for the basic version (explained in this tutorial).
    2. For stuff slightly fancier (using H-S histograms and floodFill to define a mask for the skin area) you can check the improved demo
    3. ...or you can always check out the classical camshiftdemo in samples.
  • Code at glance:

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"#include <iostream>using namespace cv;
using namespace std;/// Global Variables
Mat src; Mat hsv; Mat hue;
int bins = 25;/// Function Headers
void Hist_and_Backproj(int, void* );/** @function main */
int main( int argc, char** argv )
{/// Read the imagesrc = imread( argv[1], 1 );/// Transform it to HSVcvtColor( src, hsv, CV_BGR2HSV );/// Use only the Hue valuehue.create( hsv.size(), hsv.depth() );int ch[] = { 0, 0 };mixChannels( &hsv, 1, &hue, 1, ch, 1 );/// Create Trackbar to enter the number of binschar* window_image = "Source image";namedWindow( window_image, CV_WINDOW_AUTOSIZE );createTrackbar("* Hue  bins: ", window_image, &bins, 180, Hist_and_Backproj );Hist_and_Backproj(0, 0);/// Show the imageimshow( window_image, src );/// Wait until user exits the programwaitKey(0);return 0;
}/**
 * @function Hist_and_Backproj
 * @brief Callback to Trackbar
 */
void Hist_and_Backproj(int, void* )
{MatND hist;int histSize = MAX( bins, 2 );float hue_range[] = { 0, 180 };const float* ranges = { hue_range };/// Get the Histogram and normalize itcalcHist( &hue, 1, 0, Mat(), hist, 1, &histSize, &ranges, true, false );normalize( hist, hist, 0, 255, NORM_MINMAX, -1, Mat() );/// Get BackprojectionMatND backproj;calcBackProject( &hue, 1, 0, hist, backproj, &ranges, 1, true );/// Draw the backprojimshow( "BackProj", backproj );/// Draw the histogramint 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 );
}

Explanation

  1. Declare the matrices to store our images and initialize the number of bins to be used by our histogram:

    Mat src; Mat hsv; Mat hue;
    int bins = 25;
    

  2. Read the input image and transform it to HSV format:

    src = imread( argv[1], 1 );
    cvtColor( src, hsv, CV_BGR2HSV );
    

  3. For this tutorial, we will use only the Hue value for our 1-D histogram (check out the fancier code in the links above if you want to use the more standard H-S histogram, which yields better results):

    hue.create( hsv.size(), hsv.depth() );
    int ch[] = { 0, 0 };
    mixChannels( &hsv, 1, &hue, 1, ch, 1 );
    

    as you see, we use the function http://docs.opencv.org/modules/core/doc/operations_on_arrays.html?highlight=mixchannels#mixchannelsmixChannels to get only the channel 0 (Hue) from the hsv image. It gets the following parameters:

    • &hsv: The source array from which the channels will be copied
    • 1: The number of source arrays
    • &hue: The destination array of the copied channels
    • 1: The number of destination arrays
    • ch[] = {0,0}: The array of index pairs indicating how the channels are copied. In this case, the Hue(0) channel of &hsv is being copied to the 0 channel of &hue (1-channel)
    • 1: Number of index pairs
  4. Create a Trackbar for the user to enter the bin values. Any change on the Trackbar means a call to the Hist_and_Backproj callback function.

    char* window_image = "Source image";
    namedWindow( window_image, CV_WINDOW_AUTOSIZE );
    createTrackbar("* Hue  bins: ", window_image, &bins, 180, Hist_and_Backproj );
    Hist_and_Backproj(0, 0);
    

  5. Show the image and wait for the user to exit the program:

    imshow( window_image, src );waitKey(0);
    return 0;
    

  6. Hist_and_Backproj function: Initialize the arguments needed for calcHist. The number of bins comes from the Trackbar:

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

  7. Calculate the Histogram and normalize it to the range

    calcHist( &hue, 1, 0, Mat(), hist, 1, &histSize, &ranges, true, false );
    normalize( hist, hist, 0, 255, NORM_MINMAX, -1, Mat() );
    

  8. Get the Backprojection of the same image by calling the function calcBackProject

    MatND backproj;
    calcBackProject( &hue, 1, 0, hist, backproj, &ranges, 1, true );
    

    all the arguments are known (the same as used to calculate the histogram), only we add the backproj matrix, which will store the backprojection of the source image (&hue)

  9. Display backproj:

    imshow( "BackProj", backproj );
    

  10. Draw the 1-D Hue histogram of the image:

    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 );
    

Results

Here are the output by using a sample image ( guess what? Another hand ). You can play with the bin values and you will observe how it affects the results:

===================

normalize

Normalizes the norm or value range of an array.

C++: void normalize(InputArray src, OutputArray dst, double alpha=1, double beta=0, int norm_type=NORM_L2, int dtype=-1, InputArray mask=noArray() )
C++: void normalize(const SparseMat& src, SparseMat& dst, double alpha, int normType)
Python: cv2.normalize(src[, dst[, alpha[, beta[, norm_type[, dtype[, mask]]]]]]) → dst
Parameters:
  • src – input array.
  • dst – output array of the same size as src .
  • alpha – norm value to normalize to or the lower range boundary in case of the range normalization.
  • beta – upper range boundary in case of the range normalization; it is not used for the norm normalization.
  • normType – normalization type (see the details below).
  • dtype – when negative, the output array has the same type as src; otherwise, it has the same number of channels as src and the depth =CV_MAT_DEPTH(dtype).
  • mask – optional operation mask.

The functions normalize scale and shift the input array elements so that

(where p=Inf, 1 or 2) when normType=NORM_INF, NORM_L1, or NORM_L2, respectively; or so that

when normType=NORM_MINMAX (for dense arrays only).The optional mask specifies a sub-array to be normalized. This means that the norm or min-n-max are calculated over the sub-array, and then this sub-array is modified to be normalized. If you want to only use the mask to calculate the norm or min-max but modify the whole array, you can usenorm() andMat::convertTo().

In case of sparse matrices, only the non-zero values are analyzed and transformed. Because of this, the range transformation for sparse matrices is not allowed since it can shift the zero level.

See also

norm(),Mat::convertTo(),SparseMat::convertTo()

Back Projection相关推荐

  1. 《OpenCV3编程入门》学习笔记9 直方图与匹配(四)反向投影(back projection)

    9.4 反向投影(back projection) 9.4.1 反向投影原理 1.基本思想:   反向投影中储存的数值代表了图像中该像素属于区域的概率,计算某一特征的直方图模型,使用模型寻找图像中存在 ...

  2. Storm Trident示例function, filter, projection

    以下代码演示function, filter, projection的使用,可结合注释 省略部分代码,省略部分可参考:https://blog.csdn.net/nickta/article/deta ...

  3. 流行学习、流形学习家族、局部线性嵌入LLE、随机投影(Random Projection)、t-SNE降维及可视化

    流行学习.流形学习家族.局部线性嵌入LLE.随机投影(Random Projection).t-SNE降维及可视化 目录 流行学习.流形学习家族.局部线性嵌入LLE.随机投影(Random Proje ...

  4. 随机投影(Random Projection)降维方法

    Random Projection是一种降维方法.相对普遍的PCA的降维方法,这里介绍另一种降维方法Random Projecttion.相比于PCA,他的优势可以这样说: Random Projec ...

  5. 地球椭球体(Ellipsoid)、大地基准面(Datum)及地图投影(Projection)三者的基本概念

    地球椭球体(Ellipsoid) 众所周知我们的地球表面是一个凸凹不平的表面,而对于地球测量而言,地表是一个无法用数学公式表达的曲面,这样的曲面不能作为测量和制图的基准面.假想一个扁率极小的椭圆,绕大 ...

  6. DetachedCriteria 分页Projection取消聚合条件

    @Override     public PageBean findPaginated(DetachedCriteria detachedCriteria,PageBean pageBean) {   ...

  7. pycharm matplotlib.pyplot.figure().add_subplot()绘制三维图时报错:ValueError: Unknown projection 3d(bug)

    报错描述 出于安全考虑,CSDN不让文章标题使用英文单引号 ValueError: Unknown projection '3d' # -*- coding: utf-8 -*- "&quo ...

  8. Intel Realsense 图像投影(Projection)翻译

    原网页:Projection in RealSense SDK 2.0 This document describes the projection mathematics relating the ...

  9. 20210620 Successive projection algorithm(连续投影法)

    https://en.wikipedia.org/wiki/Projections_onto_convex_sets Algorithm The POCS algorithm solves the f ...

  10. 背水一战 Windows 10 (70) - 控件(控件基类): UIElement - Transform3D(3D变换), Projection(3D投影)...

    原文:背水一战 Windows 10 (70) - 控件(控件基类): UIElement - Transform3D(3D变换), Projection(3D投影) [源码下载] 背水一战 Wind ...

最新文章

  1. MySQL基础之select基本查询
  2. css字体设置奇怪问题
  3. 单片机中断机制对日常生活的启示_单片机原理与接口技术(高起专)阶段性作业1...
  4. 学习进度条(第十五周)
  5. 使用eclipse调试ns3配置说明
  6. asp.net单一登录
  7. Eclipse+svn+subclipse配置
  8. MikroTik RouterOS 6.x版本开始支持使用img镜像安装(U盘安装的终极解决方法)
  9. 【BZOJ】1690: [Usaco2007 Dec]奶牛的旅行
  10. tar 打包 . 开头的隐藏文件
  11. 免费手机电脑同屏神器——Mirroid
  12. 手动删除win10恢复分区
  13. Play框架文件上传
  14. btrfs filesystem 增加容量
  15. Zeppplin的安装,配置与使用
  16. 微型计算机m3500q,爆发“小”宇宙 创新与实用完美结合 ——联想ThinkCentre M3500q超小商用台式机新品发布...
  17. poi导出excel 损坏_Java使用POI生成Excel文件后打不开的问题
  18. 12 行列式01--- 定义、计算 与性质: n级行列式的性质、行列式计算
  19. Brat 标注工具 配置文件 详细说明
  20. 读书笔记-----跟任何人都聊得来

热门文章

  1. vue-element-admin(基础篇)
  2. ECCV 2018 paper
  3. 三国演义亲和度python_用python分析四大名著之三国演义
  4. 40个超有趣的Linux命令行彩蛋和游戏
  5. 【GNN】高被引图神经网络(GNN)全面综述论文
  6. ASPCMS插件,批量ASPCMS采集发布插件
  7. NYOJ234吃土豆(双层动态规划)
  8. Outlook设置规则的一点提示
  9. 关于win7快速启动栏以及显示桌面功能的还原
  10. fastadmin使用ECharts制作统计图