什么是matlab的imadjust在python中的等价物?

Posted

技术标签:

【中文标题】什么是matlab的imadjust在python中的等价物?【英文标题】:What is the equivalent of Matlab's imadjust in python? 【发布时间】:2016-09-29 10:19:24 【问题描述】:

在 python 中是否有 imadjust 的等价物。 equalizeHist 没有给出类似的结果。

【问题讨论】:

您可以轻松地从this C++ 代码实现 Python 代码。 【参考方案1】:

您可以在此处找到 imadjust 的 C++ 版本: Is there any function equivalent to Matlab's imadjust in OpenCV with C++?

而且来自@maslovw 的这个版本的python code 非常好。我只是优化了一些循环使它运行得更快。

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

【讨论】:

您能告诉我如何转换我的 BGR 图像以使用 imadjust 吗? for i in range(1, 256) 在这里编译错误,应该是for i in range(1, len(hist)) 或者只是255【参考方案2】:

一个解决方案是以下代码:

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

用法示例:

Matplotlib.pyplot 的 imshow 函数要求输入图像的范围在 [0,1] 内。以下示例展示了如何读取 RGB 或灰度图像、缩放图像并显示它。

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()

【讨论】:

【参考方案3】:

取自this 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

如果您不想设置 vin 和 vou。只需使用 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

【讨论】:

以上是关于什么是matlab的imadjust在python中的等价物?的主要内容,如果未能解决你的问题,请参考以下文章

图像处理Matlab2 灰度变换 imadjust stretchlim

matlab图像灰度调整——imadjust函数的使用

数字图像处理(MATLAB版)学习笔记——第2章 灰度变换与空间滤波

matlab中imread出现错误:

matlab中有关mean的问题

调整图像强度值