如何使用Python开发负片图像

Mik*_*bol 3 python opencv image-processing

我尝试过使用 python 中的函数反转负片图像颜色,bitwise_not()但它具有蓝色色调。我想知道如何冲洗出看起来不错的负片图像。这是我所做的结果。(我刚刚为我正在进行的新测试裁剪了负片图像,所以不要介意)

在此输入图像描述

Chr*_*itz 9

如果您不使用精确的最大值和最小值,而是使用第 1 个和第 99 个百分位数,或附近的值(0.1%?),您将获得更好的对比度。它会消除由于噪声、压缩等原因而产生的异常值。

此外,您应该想弄乱伽玛,或线性缩放值,以实现白平衡

我将应用“灰色世界假设”并缩放每个平面,使平均值为灰色。我也会搞乱伽玛,但这只是搞乱。

而且......所有这些都完全忽略了“负”和输出的伽玛映射。

import numpy as np
import cv2 as cv
import skimage

im = cv.imread("negative.png")
(bneg,gneg,rneg) = cv.split(im)

def stretch(plane):
    # take 1st and 99th percentile
    imin = np.percentile(plane, 1)
    imax = np.percentile(plane, 99)

    # stretch the image
    plane = (plane - imin) / (imax - imin)

    return plane
Run Code Online (Sandbox Code Playgroud)
b = 1 - stretch(bneg)
g = 1 - stretch(gneg)
r = 1 - stretch(rneg)

bgr = cv.merge([b,g,r])
cv.imwrite("positive.png", bgr * 255)
Run Code Online (Sandbox Code Playgroud)

清楚的

b = 1 - stretch(bneg)
g = 1 - stretch(gneg)
r = 1 - stretch(rneg)

# gray world
b *= 0.5 / b.mean()
g *= 0.5 / g.mean()
r *= 0.5 / r.mean()

bgr = cv.merge([b,g,r])
cv.imwrite("positive_grayworld.png", bgr * 255)
Run Code Online (Sandbox Code Playgroud)

灰色世界

b = 1 - np.clip(stretch(bneg), 0, 1)
g = 1 - np.clip(stretch(gneg), 0, 1)
r = 1 - np.clip(stretch(rneg), 0, 1)

# goes in the right direction
b = skimage.exposure.adjust_gamma(b, gamma=b.mean()/0.5)
g = skimage.exposure.adjust_gamma(g, gamma=g.mean()/0.5)
r = skimage.exposure.adjust_gamma(r, gamma=r.mean()/0.5)

bgr = cv.merge([b,g,r])
cv.imwrite("positive_gamma.png", bgr * 255)
Run Code Online (Sandbox Code Playgroud)

伽玛

这就是当伽玛应用于倒置图片时会发生的情况……合理容忍的传递函数是通过应用相同的因子两次而不是应用其倒数而产生的。

截屏

截屏

尝试“撤消”伽马,同时忽略值已反转......会导致严重的扭曲:

截屏

截屏

对比度拉伸的最小/最大值也会影响整个事情。

一张简单的底片照片根本不行。至少它会包括抵消黑点的杂散光。您需要对底片进行适当的扫描。


fmw*_*w42 6

这是在 Python/OpenCV 中执行此操作的一种简单方法。基本上,将图像的每个通道分别拉伸到完整的动态范围。然后重新组合。然后反转。

输入:

在此输入图像描述

import cv2
import numpy as np
import skimage.exposure

# read image
img = cv2.imread('boys_negative.png')

# separate channels
r,g,b = cv2.split(img)

# stretch each channel
r_stretch = skimage.exposure.rescale_intensity(r, in_range='image', out_range=(0,255)).astype(np.uint8)
g_stretch = skimage.exposure.rescale_intensity(g, in_range='image', out_range=(0,255)).astype(np.uint8)
b_stretch = skimage.exposure.rescale_intensity(b, in_range='image', out_range=(0,255)).astype(np.uint8)

# combine channels
img_stretch = cv2.merge([r_stretch, g_stretch, b_stretch])

# invert
result = 255 - img_stretch

cv2.imshow('input', img)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

# save results
cv2.imwrite('boys_negative_inverted.jpg', result)
Run Code Online (Sandbox Code Playgroud)

结果:

在此输入图像描述

警告:这适用于该图像,但可能不是适用于所有图像的通用解决方案。

添加

在上面,我在拉伸时没有剪辑,因为我想保留所有信息。但如果想剪辑并使用 skimage.exposure.rescale_intensity 进行拉伸,那么通过以下操作就很容易了:

import cv2
import numpy as np
import skimage.exposure

# read image
img = cv2.imread('boys_negative.png')

# separate channels
r,g,b = cv2.split(img)

# compute clip points -- clip 1% only on high side
clip_rmax = np.percentile(r, 99)
clip_gmax = np.percentile(g, 99)
clip_bmax = np.percentile(b, 99)
clip_rmin = np.percentile(r, 0)
clip_gmin = np.percentile(g, 0)
clip_bmin = np.percentile(b, 0)

# stretch each channel
r_stretch = skimage.exposure.rescale_intensity(r, in_range=(clip_rmin,clip_rmax), out_range=(0,255)).astype(np.uint8)
g_stretch = skimage.exposure.rescale_intensity(g, in_range=(clip_gmin,clip_gmax), out_range=(0,255)).astype(np.uint8)
b_stretch = skimage.exposure.rescale_intensity(b, in_range=(clip_bmin,clip_bmax), out_range=(0,255)).astype(np.uint8)

# combine channels
img_stretch = cv2.merge([r_stretch, g_stretch, b_stretch])

# invert
result = 255 - img_stretch

cv2.imshow('input', img)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

# save results
cv2.imwrite('boys_negative_inverted2.jpg', result)
Run Code Online (Sandbox Code Playgroud)

结果:

在此输入图像描述