opencv獲取灰度影象直方圖
阿新 • • 發佈:2019-02-13
影象是由不同數值(顏色)的畫素構成的,畫素值在整幅影象的分佈情況是該圖的一個重要屬性。在影象處理閾值化過程中,通常會通過獲得直方圖的方式來獲取合適的閾值來對影象進行處理。
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