import cv2
import numpy as np
import math
import copy
import numba
[文件]def histMatch(src, ref):
"""Histogram matching
The histMatch function will return the image been matched by `ref`,
the `src` and `ref` should be grayscale image
:param src: The source image, it should be `numpy.ndarray` structure,
the image read by `opencv` would be best practice
:param ref: The reference image, it should be `numpy.ndarray` structure,
the image read by `opencv` would be best practice
:return: The result image
:rtype: numpy.ndarray
"""
# first calculate the histogram of source and reference image
src_hist = cv2.calcHist([src],[0],None,[256],[0,256])
ref_hist = cv2.calcHist([ref],[0],None,[256],[0,256])
# Normalized
src_hist /= src.shape[0]*src.shape[1]
ref_hist /= ref.shape[0]*ref.shape[1]
# Cumulative distribution function
src_cdf = [0]*256
ref_cdf = [0]*256
# Calculate the cumulative probability of the original and reference histograms
for i in range(256):
if i == 0:
src_cdf[i], ref_cdf[i] = src_hist[i], ref_hist[i]
else:
src_cdf[i], ref_cdf[i] = src_cdf[i-1] + src_hist[i], ref_cdf[i-1] + ref_hist[i]
# Difference of cumulative probability
diff_cdf = np.zeros([256,256])
for i in range(256):
for j in range(256):
diff_cdf[i,j] = math.fabs(src_cdf[i] - ref_cdf[j])
# build lut
lut_o = np.zeros([256], dtype=np.uint8)
np.argmin(diff_cdf, axis=1, out=lut_o)
# using LUT to generate the result image
secmin = np.min(lut_o[lut_o>0])
lut_o[lut_o<secmin] =secmin
return cv2.LUT(src, lut_o)
[文件]@numba.jit
def lut(src, result, lut, start, factor=1):
"""LUT
This is a custom LUT implementation, the `cv2.LUT` can only work with `numpy.uint8` dtype
:param src: The source image
:param result: The result image
:param lut: The LUT table
:param start: The start value
:param factor: The factor
:return: None
"""
for i in range(src.shape[0]):
for j in range(src.shape[1]):
index = src[i, j] - start
t = lut[index] + start
result[i, j] = t / factor
[文件]def histMatch2(src, ref):
"""Histogram matching
The histmatch2 function will return the image which matched by reference image,
the source and reference image will not be 8-bit image, it used by PCA fusion
:param src: The source image, it should be `numpy.ndarray` structure,
the image read by `opencv` would be best practice
:param ref: The reference image, it should be `numpy.ndarray` structure,
the dtype would be `numpy.float32`
:return: The result image
:rtype: numpy.ndarray
"""
# convert the dtype
result = copy.deepcopy(src)
result = result.astype(np.float64)
# find max and min value
minpixel_src, maxpixel_src, _, _ = cv2.minMaxLoc(src)
minpixel_ref, maxpixel_ref, _, _ = cv2.minMaxLoc(ref)
# convert the `src` and `ref`
src = src.astype(np.float64)
ref = ref.astype(np.float64)
# transform the `src` to `ref` range
src_ref = ((src - minpixel_src) / (maxpixel_src - minpixel_src)) * (maxpixel_ref - minpixel_ref) + minpixel_ref
# copy the src and ref
src_copy = copy.deepcopy(src_ref)
ref_copy = copy.deepcopy(ref)
# calculate the factor
factor = math.ceil(4000 / (maxpixel_ref - minpixel_ref))
# factor will make histMatch possiable
src_copy = src_copy * factor
ref_copy = ref_copy * factor
src_copy = src_copy.astype(np.int)
ref_copy = ref_copy.astype(np.int)
src_copy_min, src_copy_max, _, _ = cv2.minMaxLoc(src_copy)
src_copy_min, src_copy_max = int(src_copy_min), int(src_copy_max)
histsize = src_copy_max - src_copy_min + 1
src_hist, _ = np.histogram(src_copy, bins=histsize)
ref_hist, _ = np.histogram(ref_copy, bins=histsize)
src_hist = src_hist.astype(np.float64)
ref_hist = ref_hist.astype(np.float64)
src_hist /= (src.shape[0]*src.shape[1])
ref_hist /= (ref.shape[0]*ref.shape[1])
# Cumulative distribution function
src_cdf = [0]*histsize
ref_cdf = [0]*histsize
# Calculate the cumulative probability of the original and reference histograms
for i in range(histsize):
if i == 0:
src_cdf[i], ref_cdf[i] = src_hist[i], ref_cdf[i]
else:
src_cdf[i], ref_cdf[i] = src_cdf[i-1] + src_hist[i], ref_cdf[i-1] + ref_hist[i]
# Difference of cumulative probability
diff_cdf = np.zeros([histsize,histsize])
for i in range(histsize):
for j in range(histsize):
diff_cdf[i,j] = math.fabs(src_cdf[i] - ref_cdf[j])
lut_o = np.zeros([histsize], dtype=np.int)
np.argmin(diff_cdf, axis=1, out=lut_o)
lut(src_copy, result, lut_o, src_copy_min, factor)
return result