1. 程式人生 > >opencv獲取灰度影象直方圖

opencv獲取灰度影象直方圖

影象是由不同數值(顏色)的畫素構成的,畫素值在整幅影象的分佈情況是該圖的一個重要屬性。在影象處理閾值化過程中,通常會通過獲得直方圖的方式來獲取合適的閾值來對影象進行處理。

1.灰度影象直方圖
原理以及實現方式:在灰度影象中每個畫素都以一個0~255的數值與之對應(0(黑);255(白)),這裡我們將灰度影象看做一個大矩陣,畫素值也就矩陣中每個元素值。直方圖是一個簡單的表格,表示一個影象中具有某個值的畫素的數量。因此灰度影象的直方圖具有256個專案(箱子),箱子代表畫素值,統計畫素值相同的畫素的數量存放至對應的箱子,以圖表的方式表示出來就得到灰度影象的直方圖了。

例項:

利用直方圖的方式,選擇合適的閾值,提取影象的前景(去掉背景畫素)

流程:
1.讀取要處理的影象
2.灰度處理
3.獲取灰度影象直方圖
4.得到背景影象畫素值集中的區域
5.影象二值化處理得到前景區域

示例結果:
這裡寫圖片描述

例項程式碼:

#include <iostream>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include "histogram.h"
using namespace std;

int main()
{
    cv::Mat
grayImage; cv::Mat histImage; cv::Mat binaryImage; Histogram1D hsit; cv::Mat image = cv::imread("1.png"); if (image.empty()) { cout << "read image is failure" << endl; exit(0); } cv::resize(image, image, cv::Size(image.cols / 2, image.rows /
2)); cv::imshow("Origin Image", image); cv::cvtColor(image, grayImage, CV_BGR2GRAY); histImage = hsit.getHistogramImage(grayImage); cv::imshow("histImage", histImage); cv::threshold(grayImage, binaryImage, 50, 255, CV_THRESH_BINARY_INV); cv::imshow("grayImage", grayImage); cv::imshow("binaryImage", binaryImage); waitKey(0); }

獲取直方圖的實現程式碼:

#if !defined HISTOGRAM
#define HISTOGRAM

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

using namespace cv;

class Histogram1D
{
private:
    int histSize[1];
    float hranges[2];
    const float*ranges[1];
    int channels[1];
public:
    Histogram1D()
    {
        histSize[0] = 256;
        hranges[0] = 0.0;
        hranges[1] = 256.0;
        ranges[0] = hranges;
        channels[0] = 0;
    }
    Mat getHistogram(const Mat &image)
    {
        Mat hist;
        calcHist(&image,
            1,
            channels,
            Mat(),
            hist,
            1,
            histSize,
            ranges
        );
        return hist;
    }

    Mat getHistogramImage(const Mat &image, int zoom = 1)
    {
        Mat hist = getHistogram(image);

        return getImageOfHistogram(hist, zoom);
    }
    static Mat getImageOfHistogram(const Mat &hist, int zoom)
    {
        cv::String ss;
        char midTurn[256];
        double maxVal = 0;
        double minVal = 0;
        minMaxLoc(hist, &minVal, &maxVal, 0, 0);
        int histSize = hist.rows;
        Mat histImg(histSize*zoom, histSize*zoom, CV_8U, Scalar(255));
        int hpt = static_cast<int>(0.9*histSize);
        for (int h = 0; h < histSize; h++)
        {
            float binVal = hist.at<float>(h);
            if (binVal > 0)
            {
                int intensity = static_cast<int>(binVal*hpt / maxVal);
                line(histImg, Point(h*zoom, histSize*zoom), Point(h*zoom, (histSize - intensity)*zoom), Scalar(0), zoom);
            }
        }
        for (int i = 0; i < 256; i += 25)//在直方圖上標註座標
        {
            sprintf(midTurn, "%d", i);//將數值轉換為文字
            ss = midTurn;
            putText(histImg,//目標影象
                ss,//文字
                cv::Point(i, 10),//文字位置
                cv::FONT_HERSHEY_PLAIN,//字型型別
                0.5,//字型大小
                0,//字型顏色
                1);//文字厚度
        }
        return histImg;
    }
};
#endif