反向投影(BackProjection)

 

若是一幅圖像的區域中顯示的是一種結構紋理或者一個獨特的物體,那麼這個區域的直方圖能夠看做一個機率函數,他給的是某個像素屬於該紋理或物體的機率。ios

所謂反向投影就是首先計算某一特徵的直方圖模型,而後使用模型去尋找測試圖像中存在的該特徵。函數

利用Hue直方圖解釋反向投影原理:測試

一、獲取測試圖像中每一個像素的hue數據 hi,j,並找到 hi,j 在hue直方圖中的bin的位置。ui

二、查詢hue直方圖中對應bin的數值。spa

三、將該數值存儲在新的圖像中(BackProjection),也能夠先歸一化hue直方圖數值到0-255範圍,這樣能夠直接顯示BackProjection圖像(單通道圖像)。code

四、經過對測試圖像每一個像素採起以上步驟,能夠獲得最終的BackProjection圖像。orm

 

代碼以下:blog

backprojection.h回調函數

#ifndef BACKPROJECTION_H
#define BACKPROJECTION_H

#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

//全局函數/////////////////////////////////
void hist_and_backprojection(int, void* );


#endif // BACKPROJECTION_H

backprojection.cppit

#include "backprojection.h"

extern cv::Mat src, hsv, hue;
extern int bins;

void hist_and_backprojection(int, void* )
{
    cv::MatND hist;
    //直方圖bin的數目大小
    int histSize = cv::max(bins, 2);
    float hue_range[] = {0, 180};
    const float *ranges = { hue_range };

    //計算直方圖並歸一化
    cv::calcHist(&hue,
                 1,              //圖像數量
                 0,              //通道數
                 cv::Mat(),      //不使用掩膜
                 hist,
                 1,              //直方圖維度
                 &histSize,      //每一維直方圖bin的數目
                 &ranges,        //每一維直方圖的範圍
                 true,
                 false
                 );
    //將直方圖bin的數值歸一化到0-255,可方便直接顯示反向投影圖
    cv::normalize(hist, hist, 0, 255, cv::NORM_MINMAX, -1, cv::Mat());

    //計算反向投影
    cv::MatND backproj;
    cv::calcBackProject(&hue,
                        1,               //源圖像的數目
                        0,               //用於計算反向投影值的通道列表
                        hist,            //輸入直方圖
                        backproj,        //單通道反向投影圖像
                        &ranges,         //每一維直方圖bin的範圍
                        1,
                        true);

    //顯示反向投影圖
    cv::namedWindow("BackProjection");
    cv::imshow("BackProjection", backproj);

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

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

main.cpp

#include <QtCore/QCoreApplication>
#include "backprojection.h"

//全局變量/////////////////////////////////
cv::Mat src, hsv, hue;
int bins = 25;

int main(int argc, char *argv[])
{
//    QCoreApplication a(argc, argv);
//    return a.exec();

    src = cv::imread("../image/HandIndoorColor.jpg", 1);

    //轉換到HSV
    cv::cvtColor(src, hsv, cv::COLOR_RGB2HSV);

    cv::namedWindow("hsvImg");
    cv::imshow("hsvImg", hsv);

    //分離Hue通道(即色相通道)
    hue.create(hsv.size(), hsv.depth());
    int ch[] = {0, 0};
    cv::mixChannels(&hsv, 1, &hue, 1, ch, 1);

    //建立Trackbar來輸入bin的數目
    const char *window_image = "Source image";
    cv::namedWindow(window_image, cv::WINDOW_AUTOSIZE);
    cv::createTrackbar("* Hue bins: ",window_image, &bins, 180,
                       hist_and_backprojection                   //回調函數
                       );
    hist_and_backprojection(0, 0);

    cv::imshow(window_image, src);

    //等待用戶反應
    cv::waitKey(0);
    return 0;
}

 

運行結果圖:

滑動條用於調節直方圖bin的數目。

HSV顏色空間圖像:

調節不一樣bin的數目對應的Hue直方圖:

 

調節不一樣bin的數目對應的反向投影(BackProjection)圖像:

相關文章
相關標籤/搜索