直方圖匹配原理與python、matlab實現


直方圖匹配本質上是讓兩幅圖像的累積直方圖盡量相似,累積直方圖相似了,直方圖也就相似了。

把原圖像img的直方圖匹配到參考圖像ref的直方圖,包括以下幾個步驟:

    1. 求出原圖像img的累積直方圖img_accu;

    2. 求出參考圖像ref的累積直方圖ref_accu;

    3. 灰度級g在img_accu中對應的值記為img_accu_g,找出ref_accu中與ref_accu_g最接近的值,記為ref_accu_G,記該值對應的灰度級為G;

    4. 根據g和G的對應關系,得到img經過匹配之后的直方圖。

為了說明該過程,我們舉一個簡單的例子,並把計算過程列在表格中。該例子中圖像只有10個灰度級,總共3289個像素,如下圖所示。

    

          (a) 原圖像img的直方圖                         (b) 參考圖像ref的直方圖

    

         (c) 原圖像img的累積直方圖                (d) 參考圖像ref的累積直方圖

灰度級 ref直方圖 ref累積直方圖 img直方圖
img累積直方圖 匹配之后的灰度級

 匹配之后的img累積直方圖

 

匹配之后的img直方圖

1 0 0 927 927(匹配第三列第七行的1137) 7  0  0
2 0 0 690 1617(匹配第三列第八行的1672) 8  0  0
3 20 20 535 2152(匹配第三列第九行的2362) 9  0  0
4 112 132 450 2602(匹配第三列第九行的2362) 9  0  0
5 221 353 334 2936(匹配第三列第十行的3289) 10  0  0
6 334 687 221 3157(匹配第三列第十行的3289) 10  0  0
7 450 1137 112 3269(匹配第三列第十行的3289) 10  927  927
8 535 1672 20 3289(匹配第三列第十行的3289) 10  1617  690
9 690 2362 0 3289(匹配第三列第十行的3289) 10  2152  985
10 927 3289 0 3289(匹配第三列第十行的3289) 10  3289  687

 img在匹配之后的效果如下:

   

     (a) img的經過匹配之后的累積直方圖       (b) img的經過匹配之后的直方圖

 1. OpenCV-Python實現直方圖匹配

代碼如下:

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('C:\\Users\\admin\\Desktop\\original_img3\\testimg\\lena_300_500.jpg')
ref = cv2.imread('C:\\Users\\admin\\Desktop\\original_img3\\testimg\\messi_300_500.jpg')

out = np.zeros_like(img)
_, _, colorChannel = img.shape
for i in range(colorChannel):
    print(i)
    hist_img, _ = np.histogram(img[:, :, i], 256)   # get the histogram
    hist_ref, _ = np.histogram(ref[:, :, i], 256)
    cdf_img = np.cumsum(hist_img)   # get the accumulative histogram
    cdf_ref = np.cumsum(hist_ref)

    for j in range(256):
        tmp = abs(cdf_img[j] - cdf_ref)
        tmp = tmp.tolist()
        idx = tmp.index(min(tmp))   # find the smallest number in tmp, get the index of this number
        out[:, :, i][img[:, :, i] == j] = idx

cv2.imwrite('C:\\Users\\admin\\Desktop\\lena.jpg', out)
print('Done')

效果如下:

 

2. matlab實現直方圖匹配

程序如下:

clear;
% matching img's histogram to ref's histogram.
path = 'C:\\Users\\admin\\Desktop\\original_img3\\yijia0923_9\\';
ref = imread([path, '18.jpg']);
img = imread([path, '21.jpg']);

[H, W, colorChannel] = size(ref);
out = zeros(H, W, colorChannel);
for k = 1:colorChannel
    disp(k);
    hist_ref = imhist(ref(:, :, k));    % ref的直方圖
    cumHist_ref = []; %ref的累積直方圖
    for i=1:256
        cumHist_ref = [cumHist_ref sum(hist_ref(1:i))];
    end
 
    img1 = img(:, :, k);
    hist_img = imhist(img1); %img的直方圖
    cumHist_img = []; %img的累積直方圖
    for i=1:256
        cumHist_img = [cumHist_img sum(hist_img(1:i))];
    end
 
    for i=1:256
        tmp{i} = cumHist_ref - cumHist_img(i);
        tmp{i} = abs(tmp{i});               % 找到兩個累積直方圖距離最近的點
        [a, index(i)] = min(tmp{i});       % a是tmp{i}中最小的值,index是該值對應的下標
    end
 
    imgn = zeros(H,W);
    for i = 1:H
        for j = 1:W
            imgn(i,j) = index(img1(i,j)+1)-1;    % 由原圖的灰度通過索引映射到新的灰度
        end
    end
    out(:, :, k) = imgn;
end

out=uint8(out);
% imwrite(out, [path, 'new3.jpg']);
figure; imshow(out); title('out')
disp('Done');


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM