zin*_*non 2 python opencv numpy image image-processing
我正在尝试使用对数变换来拉伸图像的直方图.基本上,我正在log对每个像素的强度应用一个操作.当我尝试更改每个像素中的图像值时,不会保存新值,但直方图看起来没问题.此外,最大值不正确.这是我的代码:
import cv2
import numpy as np
import math
from matplotlib import pyplot as plt
img = cv2.imread('messi.jpg',0)
img2 = img
for i in range(0,img2.shape[0]-1):
for j in range(0,img2.shape[1]-1):
if (math.log(1+img2[i,j],2)) < 0:
img2[i,j]=0
else:
img2[i,j] = np.int(math.log(1+img2[i,j],2))
print (np.int(math.log(1+img2[i,j],2)))
print (img2.ravel().max())
cv2.imshow('LSP',img2)
cv2.waitKey(0)
fig = plt.gcf()
fig.canvas.set_window_title('LSP histogram')
plt.hist(img2.ravel(),256,[0,256]); plt.show()
img3 = img2
B = np.int(img3.max())
A = np.int(img3.min())
print ("Maximum intensity = ", B)
print ("minimum intensity = ", A)
Run Code Online (Sandbox Code Playgroud)
这也是我得到的直方图:
但是,最大强度显示186!这根本没有应用适当的对数运算.
有任何想法吗?
您编写的代码执行应用于图像强度的对数变换.你得到如此高的杂散强度的原因是因为你的for循环是错误的.具体来说,你range的错误. range是独家结束的时间间隔,这意味着你必须去到的img.shape[0]和img.shape[1]分别,而不是img.shape[0]-1或img.shape[1]-1.因此,您缺少图像的最后一行和最后一列,并且这些不会被对数操作触及.报告的最大值来自您未触摸的最后一行或列中的其中一个像素.
一旦你纠正了这个,你就不再那么强烈了:
for i in range(0,img2.shape[0]): # Change
for j in range(0,img2.shape[1]): # Change
if (math.log(1+img2[i,j],2)) < 0:
img2[i,j]=0
else:
img2[i,j] = np.int(math.log(1+img2[i,j],2))
Run Code Online (Sandbox Code Playgroud)
这样做现在给了我们:
('Maximum intensity = ', 7)
('minimum intensity = ', 0)
Run Code Online (Sandbox Code Playgroud)
然而,你现在要得到的是一个非常黑暗的图像.您向我们展示的直方图说明所有图像像素都在黑暗范围内...大致介于两者之间[0-7].因此,如果您将图像uint8用作可视化的数据类型,则大部分图像将会变暗.请注意,我搜索了Lionel Messi图像,它是OpenCV教程的一部分,这是我发现的图像:

资料来源:https://opencv-python-tutroals.readthedocs.org/en/latest/_images/roi.jpg
您的代码将其转换为灰度,这对于您的问题来说没问题.现在,使用上面的图像,如果您实际显示直方图计数的样子以及直方图中每个bin的强度,这就是我们得到的img2:
In [41]: np.unique(img2)
Out[41]: array([0, 1, 2, 3, 4, 5, 6, 7], dtype=uint8)
In [42]: np.bincount(img2.ravel())
Out[42]: array([ 86, 88, 394, 3159, 14841, 29765, 58012, 19655])
Run Code Online (Sandbox Code Playgroud)
如您所见,大部分图像像素都在[0-7]范围之间徘徊,这就是为什么一切看起来都是黑色的原因.如果你想更好地看到这一点,或许255 / 7 = 36可以大致缩放图像,我们可以更好地看到图像:
img2 = 36*img2
cv2.imshow('LSP',img2)
cv2.waitKey(0)
Run Code Online (Sandbox Code Playgroud)
我们得到这个图片:
我也得到这个直方图:
个人看起来非常丑陋......至少对我而言.因此,如果您想要拉伸直方图,我建议您选择更有意义的图像转换.实际上,该log操作压缩了直方图的动态范围.如果要拉伸直方图,请采用相反的方法并尝试幂律运算.具体来说,给定输入强度,输出定义为:
out = c*in^(p)
Run Code Online (Sandbox Code Playgroud)
in是输入强度,p是一个幂,c是一个常数,以确保您缩放图像,以便在完成时最大强度映射到输入的相同最大强度,而不是更大.这可以通过计算来完成c:
c = (img2.max()) / (img2.max()**p)
Run Code Online (Sandbox Code Playgroud)
...... p你想要的力量在哪里?此外,通过幂律的转换可以用这个漂亮的图解释:

资料来源:http://www.nptel.ac.in/courses/117104069/chapter_8/8_14.html
基本上,小于1的功率执行强度扩展,其中较暗的强度被推向较轻的一侧.类似地,大于1的功率执行强度压缩,其中较轻的强度被推到较暗的一侧.在您的情况下,您想要扩展直方图,因此您需要第一个选项.具体来说,尝试使较小的强度朝向更大的范围.这可以通过选择小于1的功率来完成...例如尝试0.5.
你修改你的代码,使它像这样:
img2 = img2.astype(np.float) # Cast to float
c = (img2.max()) / (img2.max()**(0.5))
for i in range(0,img2.shape[0]-1):
for j in range(0,img2.shape[1]-1):
img2[i,j] = np.int(c*img2[i,j]**(0.5))
# Cast back to uint8 for display
img2 = img2.astype(np.uint8)
Run Code Online (Sandbox Code Playgroud)
这样做,我得到这个图像:
我也得到这个直方图:
如果我可以在效率方面提出建议,我不建议您遍历整个图像并单独设置每个像素......这就是不应该使用numpy数组的方式.您可以在一行代码中实现所需的矢量化.
使用旧代码,np.log2而不是math.log使用带有numpy数组的base 2 :
import cv2
import numpy as np
from matplotlib import pyplot as plt
# Your code
img = cv2.imread('messi.jpg',0)
# New code
img2 = np.log2(1 + img.astype(np.float)).astype(np.uint8)
# Back to your code
img2 = 36*img2 # Edit from before
cv2.imshow('LSP',img2)
cv2.waitKey(0)
fig = plt.gcf()
fig.canvas.set_window_title('LSP histogram')
plt.hist(img2.ravel(),256,[0,256]); plt.show()
img3 = img2
B = np.int(img3.max())
A = np.int(img3.min())
print ("Maximum intensity = ", B)
print ("minimum intensity = ", A)
cv2.destroyAllWindows() # Don't forget this
Run Code Online (Sandbox Code Playgroud)
同样,如果你想应用幂律变换,那很简单:
import cv2
import numpy as np
from matplotlib import pyplot as plt
# Your code
img = cv2.imread('messi.jpg',0)
# New code
c = (img2.max()) / (img2.max()**(0.5))
img2 = (c*img.astype(np.float)**(0.5)).astype(np.uint8)
#... rest of code as before
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7577 次 |
| 最近记录: |