OpenCV+python:直方图的应用(一)
1,直方圖均衡化 (Histogram Equalization)
假如圖像的灰度分布不均勻,其灰度分布集中在較窄的范圍內,使圖像的細節不夠清晰,對比度較低。直方圖均衡化,對圖像進行非線性拉伸,重新分配圖像的灰度值,使一定范圍內圖像的灰度值大致相等。這樣,原來直方圖中間的峰值部分對比度得到增強,而兩側的谷底部分對比度降低,輸出圖像的直方圖是一個較為平坦的直方圖。使圖像的灰度范圍拉開或使灰度均勻分布,從而增大反差,使圖像細節清晰,以達到增強的目的。
均衡化的基本思想是:盡量使得每個灰度級的像素數量相等。直方圖均衡化的另一個優勢是:不需要額外參數,整個過程是自動的;直方圖均衡化的缺點是:拉伸后有些灰度級可能不被映射到,造成圖像觀感上的顆粒感
均衡化算法
直方圖的均衡化實際也是一種灰度的變換過程,將當前的灰度分布通過一個變換函數,變換為范圍更寬、灰度分布更均勻的圖像。也就是將原圖像的直方圖修改為在整個灰度區間內大致均勻分布,因此擴大了圖像的動態范圍,增強圖像的對比度。通常均衡化選擇的變換函數是灰度的累積概率,直方圖均衡化算法的步驟:
(1)計算原圖像的灰度直方圖 P(Sk)=nk/n,其中n為像素總數,nk為灰度級Sk的像素個數
(2)計算原始圖像的累積直方圖 CDF(Sk)=∑ni/n=∑Ps(Si)
(3)Dj=L?CDF(Si),其中 Dj是目的圖像的像素,CDF(Si)是源圖像灰度為i的累積分布,L是圖像中最大灰度級(灰度圖為255)
具體代碼如下:
void equalization_self(const Mat &src, Mat &dst)
{Histogram1D hist1D;MatND hist = hist1D.getHistogram(src);hist /= (src.rows * src.cols); // 對得到的灰度直方圖進行歸一化float cdf[256] = { 0 }; // 灰度的累積概率Mat lut(1, 256, CV_8U); // 灰度變換的查找表for (int i = 0; i < 256; i++){// 計算灰度級的累積概率if (i == 0)cdf[i] = hist.at<float>(i);elsecdf[i] = cdf[i - 1] + hist.at<float>(i);lut.at<uchar>(i) = static_cast<uchar>(255 * cdf[i]); // 創建灰度的查找表}LUT(src, lut, dst); // 應用查找表,進行灰度變化,得到均衡化后的圖像}
上面代碼只是加深下對均衡化算法流程的理解,實際在OpenCV中也提供了灰度均衡化的函數。
全局直方圖均衡化 源代碼示例:
import cv2 as cv
import numpy as npdef equalHist_demo(image): #直方圖均衡化,自動調整圖像對比度,是圖像增強的一種手段gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)#首先轉化為灰度圖dst = cv.equalizeHist(gray)cv.imshow("equalHist_demo", dst)
src = cv.imread("F:/images/rice.png")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
equalHist_demo(src)
cv.waitKey(0)cv.destroyAllWindows()
運行結果:
全局直方圖均衡后背景對比度有所改善。但導致亮度過高,我們可能會丟失了大部分信息。這是因為它的直方圖并不局限于特定區域。
2,自適應直方圖均衡化(Adaptive histgram equalization/AHE)
自適應直方圖均衡化(AHE)用來提升圖像的對比度的一種計算機圖像處理技術。和普通的直方圖均衡算法不同,AHE算法通過計算圖像的局部直方圖,然后重新分布亮度來改變圖像對比度。因此,該算法更適合于改進圖像的局部對比度以及獲得更多的圖像細節。
圖像被分成稱為“圖塊”的小塊(在OpenCV中,tileSize默認為8x8)。然后像往常一樣對這些塊中的每一個進行直方圖均衡。所以在一個小區域內,直方圖會限制在一個小區域(除非有噪音)。如果有噪音,它會被放大。為避免這種情況,應用對比度限制。如果任何直方圖區間高于指定的對比度限制(在OpenCV中默認為40),則在應用直方圖均衡之前,將這些像素剪切并均勻分布到其他區間。均衡后,為了去除圖塊邊框中的瑕疵,應用雙線性插值。
算法思想:
移動模板W在圖像A上逐行移動,并且模板W的中心c(x0,y0)對應圖像上的點f(x0,y0);計算模板W區域的直方圖均衡化變化關系:g(x,y)= T(f(x,y),計算模板中心點c(x0,y0)的均衡化對應像素值:g(x0,y0) = T(f(x0,y0))。用g(x0,y0)替代f(x0,y0);逐行計算得到整幅圖像的自適應直方圖均衡化圖像。
就是在一個給定框內做直方圖均衡化,而框內所有處理(包括均衡化)只為了這個將原始中心點像素a變化到新的像素點b。
代碼實現:
function [ output_img ] = my_AHE( input_img, w)
%UNTITLED Summary of this function goes here
% Detailed explanation goes here
% 自適應直方圖均衡化
% 輸入:input_img:待處理圖像
% w: 局部處理的窗口大小[height,width,channels]=size(input_img);if channels==1src = inpit_img;
elsesrc = rgb2gray(input_img);
end%1.圖像邊界擴展
padsize=[(w-1)/2,(w-1)/2];
padSrc = padarray(src,padsize,'symmetric','both');%2.循環求解每個區域對應的值
output_img = zeros(height,width);
iter = 0;
for i=1:heightfor j=1:widthslideWindow = zeros(w,w);slideWindow = padSrc(i:i+w-1,j:j+w-1);AHE_piexl = my_AHE_piexl(slideWindow,src(i,j));output_img(i,j) = AHE_piexl;iter = iter+1;disp(iter);end
endoutput_img = uint8(output_img);endfunction [ outPiexl ] = my_AHE_piexl( window,inPiexl )
%UNTITLED2 Summary of this function goes here
% Detailed explanation goes here
% 計算局部圖像的直方圖均衡化的像素對應值
% 輸入:window: 局部圖像
% inPiexl:輸入像素
% outPiexl:輸出像素[height,width]=size(window);%1.像素灰度統計
NumPixel = zeros(1,256);
for i=1:heightfor j=1:widthgrayValue = window(i,j);NumPixel(1,grayValue+1) = NumPixel(1,grayValue+1)+1;end
end%2.計算灰度分布密度
ProbPixel = zeros(1,256);
for k=1:256ProbPixel(1,k)=NumPixel(1,k)/(height*width*1.0);
end%3.計算累積分布密度
CumuPixel = zeros(1,256);
CumuPixel(1,1) = ProbPixel(1,1);
for l=2:256CumuPixel(1,l) = CumuPixel(1,l-1)+ProbPixel(1,l);
end
CumuPixel = uint8(255 .* CumuPixel + 0.5); %取整數%4.計算灰度值映射
outPiexl = CumuPixel(inPiexl);end
同樣,上面代碼只是加深下對均衡化算法流程的理解,實際在OpenCV中也提供了灰度均衡化的函數。
源代碼示例:
import cv2 as cv
import numpy as npdef clahe_demo(image):gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)clahe = cv.createCLAHE(clipLimit=5.0, tileGridSize=(8, 8))dst = clahe.apply(gray)cv.imshow("clahe_demo", dst)src = cv.imread("F:/images/rice.png")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
clahe_demo(src)cv.waitKey(0)
cv.destroyAllWindows()
運行結果:
3,直方圖比較
對輸入的兩張圖像進行直方圖均衡化及直方圖計算步驟后,可以對兩個圖像的直方圖進行對比,并通過對比的結果得到一些我們想要的結論。
直方圖比較應用
(1)圖像相似度比較
如果我們有兩張圖像,并且這兩張圖像的直方圖一樣,或者有極高的相似度,那么在一定程度上,我們可以認為這兩幅圖是一樣的,這就是直方圖比較的應用之一。
(2)分析圖像之間關系
兩張圖像的直方圖反映了該圖像像素的分布情況,可以利用圖像的直方圖,來分析兩張圖像的關系。
直方圖比較方法
要比較兩個直方圖(H1 和 H2),首先必須要選擇一個衡量直方圖相似度的對比標準,我們設為d(H1,H2)
6.API介紹——compareHist
(1)步驟
a.先用cvtColor()把圖像從RGB色彩空間轉換到HSV色彩空間;
b.計算圖像的直方圖,然后歸一化到[0~1]之間,用到函數 calcHist() 和 normalize() ;
c.使用上述的四種方法之一進行比較,用到函數compareHist()。
(2)API介紹
函數一共有三個參數,一個輸入圖像,一個輸出圖像,一個比較方法。比較方法的取值的情況為上面的四種方法,在OpenCV中,每個都有自己的名字:Correlation ( CV_COMP_CORREL );Chi-Square ( CV_COMP_CHISQR );Intersection ( CV_COMP_INTERSECT );Bhattacharyya 距離( CV_COMP_BHATTACHARYYA )。
源代碼示例:
import cv2 as cv
import numpy as npdef create_rgb_hist(image):h, w, c = image.shapergbHist = np.zeros([16*16*16, 1], np.float32) #需要是 np.float32類型bsize = 256 / 1for row in range(h):for col in range(w):b = image[row, col, 0]g = image[row, col, 1]r = image[row, col, 2]index = np.int(b/bsize)*16*16 + np.int(g/bsize)*16 + np.int(r/bsize)rgbHist[np.int(index), 0] = rgbHist[np.int(index), 0] + 1return rgbHistdef hist_compare(image1, image2):hist1 = create_rgb_hist(image1)hist2 = create_rgb_hist(image2)match1 = cv.compareHist(hist1, hist2, cv.HISTCMP_BHATTACHARYYA)#巴氏距離,越小越相似match2 = cv.compareHist(hist1, hist2, cv.HISTCMP_CORREL)#相關性,越大越相似match3 = cv.compareHist(hist1, hist2, cv.HISTCMP_CHISQR)#卡方,越小越相似print("巴氏距離: %s, 相關性: %s, 卡方: %s"%(match1, match2, match3))image1 = cv.imread("F:/images/lena.png")
image2 = cv.imread("F:/images/lenanoise.png")
cv.imshow("image1", image1)
cv.imshow("image2", image2)
hist_compare(image1, image2)cv.waitKey(0)cv.destroyAllWindows()
運行結果:
巴氏距離: 0.09072200336618969, 相關性: 0.9788106004024394, 卡方: 164.3082768373199
以上數據說明兩張圖很相似。如果圖像大小不一致需要對直方圖進行歸一化。
總結
以上是生活随笔為你收集整理的OpenCV+python:直方图的应用(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 这个值多少?必采纳
- 下一篇: 复联4定档4月24号,请列举复联4上映后