Python 在 OpenCV 中标准化图像
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38025838/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Normalizing images in OpenCV
提问by Nipuni Chandimali
I wrote the following code to work normalize an image using NORM_L1 in OpenCV. But the output image was just black.How to solve this ?
我编写了以下代码来使用 OpenCV 中的 NORM_L1 对图像进行标准化。但输出图像只是黑色。如何解决这个问题?
import cv2
import numpy as np
import Image
img = cv2.imread('img7.jpg')
gray_image = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
a = np.asarray(gray_image)
dst = np.zeros(shape=(5,2))
b=cv2.normalize(a,dst,0,255,cv2.NORM_L1)
im = Image.fromarray(b)
im.save("img50.jpg")
cv2.waitKey(0)
cv2.destroyAllWindows()
回答by Sounak
If you want to change the range to [0, 1], make sure the output data type is float
.
如果要将范围更改为 [0, 1],请确保输出数据类型为float
。
image = cv2.imread("lenacolor512.tiff", cv2.IMREAD_COLOR) # uint8 image
norm_image = cv2.normalize(image, None, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_32F)
回答by Andrey Smorodov
When you normalize a matrix using NORM_L1, you are dividing every pixel value by the sum of absolute values of all the pixels in the image. As a result, all pixel values become much less than 1 and you get a black image. Try NORM_MINMAX instead of NORM_L1.
当您使用 NORM_L1 对矩阵进行归一化时,您将每个像素值除以图像中所有像素的绝对值之和。结果,所有像素值都变得远小于 1,您会得到一张黑色图像。尝试 NORM_MINMAX 而不是 NORM_L1。
回答by nathancy
The other answers normalize an image based on the entire image. But if your image has a predominant color (such as black), it will mask out the features that you're trying to enhance since it will not be as pronounced. To get around this limitation, we can normalize the image based on a subsection region of interest (ROI). Essentially we will normalize based on the section of the image that we want to enhance instead of equally treating each pixel with the same weight. Take for instance this earth image:
其他答案根据整个图像对图像进行标准化。但是,如果您的图像具有主要颜色(例如黑色),它将掩盖您试图增强的特征,因为它不会那么明显。为了解决这个限制,我们可以根据感兴趣的子区域 (ROI) 对图像进行归一化。本质上,我们将根据我们想要增强的图像部分进行标准化,而不是用相同的权重平等对待每个像素。以这张地球图像为例:
Input image ->
Normalization based on entire image
->
基于整个图像的输入图像归一化
If we want to enhance the clouds by normalizing based on the entire image, the result will not be very sharp and will be over saturated due to the black background. The features to enhance are lost. So to obtain a better result we can crop a ROI, normalize based on the ROI, and then apply the normalization back onto the original image. Say we crop the ROI highlighted in green:
如果我们想通过基于整个图像的归一化来增强云层,结果不会很清晰,并且会由于黑色背景而过度饱和。要增强的功能丢失了。因此,为了获得更好的结果,我们可以裁剪一个 ROI,根据 ROI 进行归一化,然后将归一化应用回原始图像。假设我们裁剪了以绿色突出显示的 ROI:
This gives us this ROI
这给了我们这个投资回报率
The idea is to calculate the mean and standard deviation of the ROI and then clip the frame based on the lower and upper range. In addition, we could use an offset to dynamically adjust the clip intensity. From here we normalize the original image to this new range. Here's the result:
想法是计算ROI的均值和标准差,然后根据上下范围裁剪帧。此外,我们可以使用偏移量来动态调整剪辑强度。从这里我们将原始图像标准化到这个新范围。结果如下:
Before ->
After
之前->
之后
Code
代码
import cv2
import numpy as np
# Load image as grayscale and crop ROI
image = cv2.imread('1.png', 0)
x, y, w, h = 364, 633, 791, 273
ROI = image[y:y+h, x:x+w]
# Calculate mean and STD
mean, STD = cv2.meanStdDev(ROI)
# Clip frame to lower and upper STD
offset = 0.2
clipped = np.clip(image, mean - offset*STD, mean + offset*STD).astype(np.uint8)
# Normalize to range
result = cv2.normalize(clipped, clipped, 0, 255, norm_type=cv2.NORM_MINMAX)
cv2.imshow('image', image)
cv2.imshow('ROI', ROI)
cv2.imshow('result', result)
cv2.waitKey()
The difference between normalizing based on the entire image vs a specific section of the ROI can be visualized by applying a heatmap to the result. Notice the difference on how the clouds are defined.
可以通过将热图应用于结果来可视化基于整个图像的归一化与 ROI 的特定部分之间的差异。注意云的定义方式的不同。
Input image ->
heatmap
输入图像->
热图
Normalized on entire image ->
heatmap
在整个图像->
热图上标准化
Normalized on ROI ->
heatmap
在 ROI->
热图上标准化
Heatmap code
热图代码
import matplotlib.pyplot as plt
import numpy as np
import cv2
image = cv2.imread('result.png', 0)
colormap = plt.get_cmap('inferno')
heatmap = (colormap(image) * 2**16).astype(np.uint16)[:,:,:3]
heatmap = cv2.cvtColor(heatmap, cv2.COLOR_RGB2BGR)
cv2.imshow('image', image)
cv2.imshow('heatmap', heatmap)
cv2.waitKey()
Note:The ROI bounding box coordinates were obtained using how to get ROI Bounding Box Coordinates without Guess & Checkand heatmap code was from how to convert a grayscale image to heatmap image with Python OpenCV
注意:ROI 边界框坐标是使用how to get ROI Bounding Box Coordinates without Guess & Check 获得的,热图代码来自how to convert a grayscale image to heatmap image with Python OpenCV