【发布时间】:2013-09-27 21:24:18
【问题描述】:
我正在使用 numpy 和 scipy 来处理使用 CCD 相机拍摄的大量图像。这些图像具有许多具有非常大(或小)值的热(和死)像素。这些会干扰其他图像处理,因此需要将其删除。不幸的是,尽管一些像素停留在 0 或 255 并且在所有图像中始终处于相同的值,但仍有一些像素在几分钟内暂时停留在其他值(数据跨越很长时间)。
我想知道是否有一种方法可以识别(和删除)已经在 python 中实现的热点像素。如果没有,我想知道这样做的有效方法是什么。通过与相邻像素进行比较,热/死像素相对容易识别。我可以看到编写一个循环来查看每个像素,将其值与其 8 个最近邻居的值进行比较。或者,使用某种卷积来生成更平滑的图像,然后从包含热像素的图像中减去它似乎更好,使它们更容易识别。
我已经在下面的代码中尝试过这种“模糊方法”,它工作正常,但我怀疑它是最快的。此外,它在图像的边缘会混淆(可能是因为 gaussian_filter 函数正在进行卷积并且卷积在边缘附近变得奇怪)。那么,有没有更好的方法来解决这个问题?
示例代码:
import numpy as np
import matplotlib.pyplot as plt
import scipy.ndimage
plt.figure(figsize=(8,4))
ax1 = plt.subplot(121)
ax2 = plt.subplot(122)
#make a sample image
x = np.linspace(-5,5,200)
X,Y = np.meshgrid(x,x)
Z = 255*np.cos(np.sqrt(x**2 + Y**2))**2
for i in range(0,11):
#Add some hot pixels
Z[np.random.randint(low=0,high=199),np.random.randint(low=0,high=199)]= np.random.randint(low=200,high=255)
#and dead pixels
Z[np.random.randint(low=0,high=199),np.random.randint(low=0,high=199)]= np.random.randint(low=0,high=10)
#Then plot it
ax1.set_title('Raw data with hot pixels')
ax1.imshow(Z,interpolation='nearest',origin='lower')
#Now we try to find the hot pixels
blurred_Z = scipy.ndimage.gaussian_filter(Z, sigma=2)
difference = Z - blurred_Z
ax2.set_title('Difference with hot pixels identified')
ax2.imshow(difference,interpolation='nearest',origin='lower')
threshold = 15
hot_pixels = np.nonzero((difference>threshold) | (difference<-threshold))
#Don't include the hot pixels that we found near the edge:
count = 0
for y,x in zip(hot_pixels[0],hot_pixels[1]):
if (x != 0) and (x != 199) and (y != 0) and (y != 199):
ax2.plot(x,y,'ro')
count += 1
print 'Detected %i hot/dead pixels out of 20.'%count
ax2.set_xlim(0,200); ax2.set_ylim(0,200)
plt.show()
然后输出:
【问题讨论】:
-
尝试一个更简单的案例:使用中值滤波制作另一张图像(例如,通过 3x3 模式)并计算您的图像和过滤后的图像之间差异的绝对值。用过滤值替换具有较大差异值(假设为 100)的原始图像像素。您可以通过差异统计自动获得阈值。
-
@Eddy_Em,感谢您提出中值滤波器 - 这似乎比高斯滤波器更好。另外,我喜欢使用差异数组的统计信息设置阈值的想法。我尝试采用标准偏差,这似乎运作良好。 (我将阈值设置为标准偏差的 5 倍。)但是,我对您将差异数组的倍数添加到图像数组的建议感到困惑。这是做什么的?
-
哦,不:我的意思是您搜索像素以通过某个阈值清除差异数组中的像素。
-
好的,这就是我现在正在做的事情。这似乎与中值滤波器一起工作得很好。仍然存在边缘效应,中值滤波器在边缘附近产生不同的结果,因此看起来那里有很多热像素。知道如何使它在边缘附近工作吗?目前,我只是忽略了边缘,但这似乎是一个不雅的解决方案。
-
好问题!有大量可用的天文学策略,例如github.com/astropy/astroscrappy
标签: python image-processing numpy camera scipy