首页 > 解决方案 > PIL.ImageOps.autocontrast() 等效于 opencv2

问题描述

我在 PIL 或图像处理中制作了一个脚本,但我也想在视频中工作,所以我正在用 opencv2-python 重写它。我遇到的问题是没有等效的 PIL 自动对比度,特别是截止属性。

如果您有解决方案,请告诉我。

PIL.ImageOps.autocontrast()


编辑:

我将添加一些例子来展示我想要做什么,我期待什么以及我得到什么结果。

示例图片在这里

PIL 代码

from PIL import Image, ImageOps
img = Image.open("his_equi.jpg").convert("L") #name of the file is his_equi.jpg
edited = ImageOps.autocontrast(img, cutoff=3)
edited.save("hiseqpil_1.jpg")

PIL 输出在这里


CV2 代码

import cv2
img = cv2.imread("his_equi.jpg", 0)

alpha = 1.8  # Contrast control (1.0-3.0)
beta = 0  # Brightness control (0-100)

img = cv2.convertScaleAbs(img, alpha=alpha, beta=beta)
clahe = cv2.createCLAHE(clipLimit=3, tileGridSize=(2, 2))
img = clahe.apply(img)

cv2.imwrite('hiscl_2.jpg', img)

CV2 输出在这里


我试过 cv2.equalizeHist()

import cv2
img = cv2.imread("his_equi.jpg", 0)
img = cv2.equalizeHist(img)
cv2.imwrite('hiscl_2.jpg', img)

cv2.equalizeHist()在这里输出

你可以看到我希望最暗的像素变成黑色,即使它们是灰色的,而浅灰色的像素变成白色。我认为这被称为标准化图像。

标签: pythonopencvimage-processingcomputer-visionpython-imaging-library

解决方案


我从这个github引用了一个autocontrast_func

def autocontrast_func(img, cutoff=0):
    '''
        same output as PIL.ImageOps.autocontrast
    '''
    n_bins = 256
    def tune_channel(ch):
        n = ch.size
        cut = cutoff * n // 100
        if cut == 0:
            high, low = ch.max(), ch.min()
        else:
            hist = cv2.calcHist([ch], [0], None, [n_bins], [0, n_bins])
            low = np.argwhere(np.cumsum(hist) > cut)
            low = 0 if low.shape[0] == 0 else low[0]
            high = np.argwhere(np.cumsum(hist[::-1]) > cut)
            high = n_bins - 1 if high.shape[0] == 0 else n_bins - 1 - high[0]
        if high <= low:
            table = np.arange(n_bins)
        else:
            scale = (n_bins - 1) / (high - low)
            offset = -low * scale
            table = np.arange(n_bins) * scale + offset
            table[table < 0] = 0
            table[table > n_bins - 1] = n_bins - 1
        table = table.clip(0, 255).astype(np.uint8)
        return table[ch]
    channels = [tune_channel(ch) for ch in cv2.split(img)]
    out = cv2.merge(channels)
    return out

它似乎与 PIL 自动对比度匹配得很好。

from PIL import Image
import requests

url = 'https://i.stack.imgur.com/JJ4Se.jpg'
im = Image.open(requests.get(url, stream=True).raw)
arr_im = autocontrast_func(np.array(im), cutoff=3)
Image.fromarray(arr_im)

推荐阅读