python 直方图匹配_直方图匹配原理与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');

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值