计算对比度图

2024-04-19 20:13:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在NxN窗口中计算每个像素周围的对比度,并将结果保存在新图像中,其中新图像中的每个像素是旧图像中其周围区域的对比度。从另一个帖子中我得到了以下信息:

1) Convert the image to say LAB and get the L channel
2) Compute the max for an NxN neighborhood around each pixel
3) Compute the min for an NxN neighborhood around each pixel
4) Compute the contrast from the equation above at each pixel.
5) Insert the contrast as a pixel value in new image.

目前我有以下几点:

def cmap(roi):
    max = roi.reshape((roi.shape[0] * roi.shape[1], 3)).max(axis=0)
    min = roi.reshape((roi.shape[0] * roi.shape[1], 3)).min(axis=0)
    contrast = (max - min) / (max + min)
    return contrast


def cm(img):
    # convert to LAB color space
    lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)

    # separate channels
    L, A, B = cv2.split(lab)

    img_shape = L.shape

    size = 5

    shape = (L.shape[0] - size + 1, L.shape[1] - size + 1, size, size)
    strides = 2 * L.strides
    patches = np.lib.stride_tricks.as_strided(L, shape=shape, strides=strides)
    patches = patches.reshape(-1, size, size)

    output_img = np.array([cmap(roi) for roi in patches])
    cv2.imwrite("labtest.png", output_img)

代码抱怨roi的大小。有更好的(Python式)方法来做我想做的事吗


Tags: the图像imgsizemincv2maxcompute
1条回答
网友
1楼 · 发布于 2024-04-19 20:13:11

可以使用DilationErosion形态学运算来查找NxN邻域的最大值和最小值

  • NxN的扩张相当于NxN邻域的最大
  • NxN的侵蚀相当于NxN邻域的最小

使用形态学运算使解决方案比“手动”将图像分割成小块要简单得多

您可以使用以下阶段:

  • 转换到实验室颜色空间并获得L通道
  • 使用“扩张”形态学运算(扩张相当于在NxN邻域中找到最大像素)
  • 使用“腐蚀”形态学操作(扩张相当于在NxN邻域中找到最大像素)
  • 将图像转换为float类型(使用除法操作之前需要)
  • 计算对比度图(对比度图的范围为[0,1])
  • 将对比度贴图转换为带有舍入的uint8类型-转换降低了精度,因此我不能推荐它(但我假设您需要转换以获得图像输出)

以下是完整的代码示例:

import numpy as np
import cv2

size_n = 5 # NxN neighborhood around each pixel

# Read input image
img = cv2.imread('chelsea.png')

# Convert to LAB color space
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)

# Get the L channel
L = lab[:, :, 0]

# Use "dilate" morphological operation (dilate is equivalent to finding maximum pixel in NxN neighborhood)
img_max = cv2.morphologyEx(L, cv2.MORPH_DILATE, np.ones((size_n, size_n)))

# Use "erode" morphological operation (dilate is equivalent to finding maximum pixel in NxN neighborhood)
img_min = cv2.morphologyEx(L, cv2.MORPH_ERODE, np.ones((size_n, size_n)))

# Convert to type float (required before using division operation)
img_max = img_max.astype(float)
img_min = img_min.astype(float)

# Compute contrast map (range of img_contrast is [0, 1])
img_contrast = (img_max - img_min) / (img_max + img_min)

# Convert contrast map to type uint8 with rounding - the conversion loosed accuracy, so I can't recommend it.
# Note: img_contrast_uint8 is scaled by 255 (scaled by 255 relative to the original formula).
img_contrast_uint8 = np.round(img_contrast*255).astype(np.uint8)

# Show img_contrast as output
cv2.imshow('img_contrast', img_contrast_uint8)
cv2.waitKey()
cv2.destroyAllWindows()

输入图像:
enter image description here

L图像:
enter image description here

img_max:
enter image description here

img_min
enter image description here

对比图img_contrast_uint8
enter image description here

相关问题 更多 >