检测图像是否为负片
Detect if an image is negative
我正在尝试清理一些胸部 X 光数据以提供给 CNN。在我的数据集中,目前有许多图像的骨骼显示为白色(像素值高于背景),如下所示:
而其他人则以比背景更深的颜色显示骨骼,如下所示:
你能告诉我如何标记这两者吗?我没有关于图像的其他外部信息,但可以假设它们大小相同 (
假设它们具有相同的大小(大约 1000x2000)并且第一行像素有超过 1 个不同的值(即不是空白边框),我写了这个简单的代码来比较中间的像素到左上角(可能是背景的一部分)。
if img[0,0] > img[500, 500]: # if background lighter than center
img = 255 - img # make the image negative
即使从我发布的这些示例中您也可以看出,这种比较并不总是一个好的指标(有时背景周围有光晕或 [500,500] 中的像素可能与背景相似)。有没有更可靠的其他方法来检测这种图像是否为负片?
考虑到数据集中有一些细节和阴影很少的图像,例如
一个可能的解决方案涉及均衡输入图像,然后阈值处理应用固定阈值。我们可以估计 白色像素的数量 并与阈值进行比较以决定是否需要应用校正。
我们来看代码:
# Imports:
import numpy as np
import cv2
# Image path
path = "D://opencvImages//"
fileName = "RPWBn.png"
# Reading an image in default mode:
inputImage = cv2.imread(path + fileName)
# Convert RGB to grayscale:
originalGrayscale = cv2.cvtColor(inputImage, cv2.COLOR_BGR2GRAY)
# Equalize histogram
grayscaleImage = cv2.equalizeHist(originalGrayscale)
# It might be interesting to you to check out the image equalization:
cv2.imshow("Image Equalized", grayscaleImage)
cv2.waitKey(0)
# Binarize the image with a fixed threshold:
minThresh = 128
_, binaryImage = cv2.threshold(grayscaleImage, minThresh, 255, cv2.THRESH_BINARY)
# Compute the percent of white pixels:
(imageHeight, imageWidth) = binaryImage .shape[:2]
whitePercent = cv2.countNonZero(binaryImage)/(imageHeight * imageWidth)
然后,我们根据阈值检查此值,看看是否必须应用更正。您可以选择校正原始图像和均衡后的图像:
if whitePercent > 0.5:
print("Correcting images...")
# Correct the original (unequalized) image:
originalGrayscale = 255 - originalGrayscale
cv2.imshow("Correction - Original Image", originalGrayscale)
# Correct the equalized image:
grayscaleImage = 255 - grayscaleImage
cv2.imshow("Correction - Equalized Image", grayscaleImage )
cv2.waitKey(0)
第二张图片已更正。以下是两种可能结果的图片:
原文倒转:
均衡反转:
现在,除了图像反转,您可能还需要做一些额外的事情 post-processing 来提高原件的亮度和对比度。我们可以使用 CLAHE 方法来实现这一点。让我们 post-process 原始的未均衡图像:
# Improve the brightness + contrast of the original image via
# CLAHE.
# Gray to BGR conversion:
originalGrayscale = cv2.cvtColor(originalGrayscale , cv2.COLOR_GRAY2BGR)
# Conversion to LAB:
lab = cv2.cvtColor(originalGrayscale, cv2.COLOR_BGR2LAB)
# Split the channels:
l, a, b = cv2.split(lab)
# Apply CLAHE to L-channel:
# You might need to fiddle with the parameters:
clahe = cv2.createCLAHE(clipLimit=7.0, tileGridSize=(1, 1))
cl = clahe.apply(l)
# Merge the CLAHE enhanced L-channel with the a and b channel:
limg = cv2.merge((cl, a, b))
# Conversion from LAB to BGR:
final = cv2.cvtColor(limg, cv2.COLOR_LAB2BGR)
cv2.imshow("Original Corrected and Enhanced", final)
cv2.waitKey(0)
这是增强后的图像:
按照Christoph Rackwitz的建议,我用这种方法得到了很好的结果:
- 可选择规范化图像
- 从图像中提取角点,更有可能是背景(我只考虑了顶角)
- 从图像中提取中心
- 将区域与阈值(图像的固定或平均灰度值)进行比较,得到真值列表
- 比较高于阈值的像素数量(以百分比表示)以确定背景比图像中心亮还是暗:因此决定反转值。
def invert_if_negative(img):
img = my_contrast_stretch(img)
# assuming image has fixed size of (1396, 1676)
# corners
top_left = img[:200, :200].flatten()
top_right = img[:200, 1250:].flatten()
# more or less center
center = img[1000:1300, 500:800].flatten()
threshold = 120 # or computed from average
top_left = top_left > threshold
top_right = top_right > threshold
center = center > threshold
perc_white_corners = (sum(top_left) + sum(top_right)) / (len(top_left) + len(top_right))
perc_white_center = sum(center) / len(center)
if perc_white_corners > perc_white_center:
img = 255 - img
return img
def my_contrast_stretch(img):
if img.dtype == np.float64:
img = (img * 255).astype(np.uint8)
M=np.max(img)
m=np.min(img)
res = img - m
res = res * (255 / (M - m))
return res.astype(np.uint8)
我正在尝试清理一些胸部 X 光数据以提供给 CNN。在我的数据集中,目前有许多图像的骨骼显示为白色(像素值高于背景),如下所示:
而其他人则以比背景更深的颜色显示骨骼,如下所示:
你能告诉我如何标记这两者吗?我没有关于图像的其他外部信息,但可以假设它们大小相同 (
假设它们具有相同的大小(大约 1000x2000)并且第一行像素有超过 1 个不同的值(即不是空白边框),我写了这个简单的代码来比较中间的像素到左上角(可能是背景的一部分)。
if img[0,0] > img[500, 500]: # if background lighter than center
img = 255 - img # make the image negative
即使从我发布的这些示例中您也可以看出,这种比较并不总是一个好的指标(有时背景周围有光晕或 [500,500] 中的像素可能与背景相似)。有没有更可靠的其他方法来检测这种图像是否为负片?
考虑到数据集中有一些细节和阴影很少的图像,例如
一个可能的解决方案涉及均衡输入图像,然后阈值处理应用固定阈值。我们可以估计 白色像素的数量 并与阈值进行比较以决定是否需要应用校正。
我们来看代码:
# Imports:
import numpy as np
import cv2
# Image path
path = "D://opencvImages//"
fileName = "RPWBn.png"
# Reading an image in default mode:
inputImage = cv2.imread(path + fileName)
# Convert RGB to grayscale:
originalGrayscale = cv2.cvtColor(inputImage, cv2.COLOR_BGR2GRAY)
# Equalize histogram
grayscaleImage = cv2.equalizeHist(originalGrayscale)
# It might be interesting to you to check out the image equalization:
cv2.imshow("Image Equalized", grayscaleImage)
cv2.waitKey(0)
# Binarize the image with a fixed threshold:
minThresh = 128
_, binaryImage = cv2.threshold(grayscaleImage, minThresh, 255, cv2.THRESH_BINARY)
# Compute the percent of white pixels:
(imageHeight, imageWidth) = binaryImage .shape[:2]
whitePercent = cv2.countNonZero(binaryImage)/(imageHeight * imageWidth)
然后,我们根据阈值检查此值,看看是否必须应用更正。您可以选择校正原始图像和均衡后的图像:
if whitePercent > 0.5:
print("Correcting images...")
# Correct the original (unequalized) image:
originalGrayscale = 255 - originalGrayscale
cv2.imshow("Correction - Original Image", originalGrayscale)
# Correct the equalized image:
grayscaleImage = 255 - grayscaleImage
cv2.imshow("Correction - Equalized Image", grayscaleImage )
cv2.waitKey(0)
第二张图片已更正。以下是两种可能结果的图片:
原文倒转:
均衡反转:
现在,除了图像反转,您可能还需要做一些额外的事情 post-processing 来提高原件的亮度和对比度。我们可以使用 CLAHE 方法来实现这一点。让我们 post-process 原始的未均衡图像:
# Improve the brightness + contrast of the original image via
# CLAHE.
# Gray to BGR conversion:
originalGrayscale = cv2.cvtColor(originalGrayscale , cv2.COLOR_GRAY2BGR)
# Conversion to LAB:
lab = cv2.cvtColor(originalGrayscale, cv2.COLOR_BGR2LAB)
# Split the channels:
l, a, b = cv2.split(lab)
# Apply CLAHE to L-channel:
# You might need to fiddle with the parameters:
clahe = cv2.createCLAHE(clipLimit=7.0, tileGridSize=(1, 1))
cl = clahe.apply(l)
# Merge the CLAHE enhanced L-channel with the a and b channel:
limg = cv2.merge((cl, a, b))
# Conversion from LAB to BGR:
final = cv2.cvtColor(limg, cv2.COLOR_LAB2BGR)
cv2.imshow("Original Corrected and Enhanced", final)
cv2.waitKey(0)
这是增强后的图像:
按照Christoph Rackwitz的建议,我用这种方法得到了很好的结果:
- 可选择规范化图像
- 从图像中提取角点,更有可能是背景(我只考虑了顶角)
- 从图像中提取中心
- 将区域与阈值(图像的固定或平均灰度值)进行比较,得到真值列表
- 比较高于阈值的像素数量(以百分比表示)以确定背景比图像中心亮还是暗:因此决定反转值。
def invert_if_negative(img):
img = my_contrast_stretch(img)
# assuming image has fixed size of (1396, 1676)
# corners
top_left = img[:200, :200].flatten()
top_right = img[:200, 1250:].flatten()
# more or less center
center = img[1000:1300, 500:800].flatten()
threshold = 120 # or computed from average
top_left = top_left > threshold
top_right = top_right > threshold
center = center > threshold
perc_white_corners = (sum(top_left) + sum(top_right)) / (len(top_left) + len(top_right))
perc_white_center = sum(center) / len(center)
if perc_white_corners > perc_white_center:
img = 255 - img
return img
def my_contrast_stretch(img):
if img.dtype == np.float64:
img = (img * 255).astype(np.uint8)
M=np.max(img)
m=np.min(img)
res = img - m
res = res * (255 / (M - m))
return res.astype(np.uint8)