Existe-t-il un équivalent de imadjust en python. equalizeHist ne donne pas un résultat similaire.
Réponses
Trop de publicités?Tiré de cette solution
import numpy as np
import bisect
def imadjust(src, tol=1, vin=[0,255], vout=(0,255)):
# src : input one-layer image (numpy array)
# tol : tolerance, from 0 to 100.
# vin : src image bounds
# vout : dst image bounds
# return : output img
dst = src.copy()
tol = max(0, min(100, tol))
if tol > 0:
# Compute in and out limits
# Histogram
hist = np.zeros(256, dtype=np.int)
for r in range(src.shape[0]):
for c in range(src.shape[1]):
hist[src[r,c]] += 1
# Cumulative histogram
cum = hist.copy()
for i in range(1, len(hist)):
cum[i] = cum[i - 1] + hist[i]
# Compute bounds
total = src.shape[0] * src.shape[1]
low_bound = total * tol / 100
upp_bound = total * (100 - tol) / 100
vin[0] = bisect.bisect_left(cum, low_bound)
vin[1] = bisect.bisect_left(cum, upp_bound)
# Stretching
scale = (vout[1] - vout[0]) / (vin[1] - vin[0])
for r in range(dst.shape[0]):
for c in range(dst.shape[1]):
vs = max(src[r,c] - vin[0], 0)
vd = min(int(vs * scale + 0.5) + vout[0], vout[1])
dst[r,c] = vd
return dst
si vous ne voulez pas définir le vin et le vou. Utilisez simplement cv2.equalizeHist.
@jit
def hisEqul(img):
return cv2.equalizeHist(img)
@jit
def hisEqulColor(img):
ycrcb = cv2.cvtColor(img, cv2.COLOR_BGR2YCR_CB)
channels = cv2.split(ycrcb)
cv2.equalizeHist(channels[0], channels[0])
cv2.merge(channels, ycrcb)
cv2.cvtColor(ycrcb, cv2.COLOR_YCR_CB2BGR, img)
return img
Vous pouvez trouver la version C++ de la imadjust ici : Existe-t-il une fonction équivalente à imadjust de Matlab dans OpenCV avec C++ ?
Et cette version de python code J'ai juste optimisé quelques boucles pour le faire tourner un peu plus vite.
import numpy as np
import bisect
from numba import jit
@jit
def imadjust(src, tol=1, vin=[0,255], vout=(0,255)):
# src : input one-layer image (numpy array)
# tol : tolerance, from 0 to 100.
# vin : src image bounds
# vout : dst image bounds
# return : output img
assert len(src.shape) == 2 ,'Input image should be 2-dims'
tol = max(0, min(100, tol))
if tol > 0:
# Compute in and out limits
# Histogram
hist = np.histogram(src,bins=list(range(256)),range=(0,255))[0]
# Cumulative histogram
cum = hist.copy()
for i in range(1, 256): cum[i] = cum[i - 1] + hist[i]
# Compute bounds
total = src.shape[0] * src.shape[1]
low_bound = total * tol / 100
upp_bound = total * (100 - tol) / 100
vin[0] = bisect.bisect_left(cum, low_bound)
vin[1] = bisect.bisect_left(cum, upp_bound)
# Stretching
scale = (vout[1] - vout[0]) / (vin[1] - vin[0])
vs = src-vin[0]
vs[src<vin[0]]=0
vd = vs*scale+0.5 + vout[0]
vd[vd>vout[1]] = vout[1]
dst = vd
return dst
Une solution est le morceau de code suivant :
def imadjust(x,a,b,c,d,gamma=1):
# Similar to imadjust in MATLAB.
# Converts an image range from [a,b] to [c,d].
# The Equation of a line can be used for this transformation:
# y=((d-c)/(b-a))*(x-a)+c
# However, it is better to use a more generalized equation:
# y=((x-a)/(b-a))^gamma*(d-c)+c
# If gamma is equal to 1, then the line equation is used.
# When gamma is not equal to 1, then the transformation is not linear.
y = (((x - a) / (b - a)) ** gamma) * (d - c) + c
return y
Exemple d'utilisation :
La fonction imshow de Matplotlib.pyplot requiert que la plage de l'image d'entrée soit comprise entre [0,1]. L'exemple suivant montre comment lire une image RVB ou à échelle de gris, mettre l'image à l'échelle et l'afficher.
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
image = Image.open(fname)
arr = np.asarray(image)
arr2=imadjust(arr,arr.min(),arr.max(),0,1)
fig = plt.figure()
fig.suptitle('image')
plt.imshow(arr2)
plt.show()