在python中自动删除图像中的热/死像素
我正在使用numpy和scipy处理用CCD相机拍摄的大量图像。这些图像有许多热(和死)像素,其值非常大(或很小)。这些会干扰其他图像处理,因此需要将其删除。不幸的是,尽管一些像素停留在0或255,并且在所有图像中始终处于相同的值,但仍有一些像素暂时停留在其他值上几分钟(数据跨越数小时) 我想知道是否有一种方法可以识别(和删除)python中已经实现的热点像素。如果没有,我想知道什么是一个有效的方法来这样做。通过与相邻像素进行比较,热/死像素相对容易识别。我可以看到写一个循环,查看每个像素,将其值与其8个最近邻的值进行比较。或者,使用某种卷积生成更平滑的图像,然后从包含热像素的图像中减去它,使它们更容易识别,这似乎更好 我在下面的代码中尝试过这种“模糊方法”,效果不错,但我怀疑它是否最快。此外,它在图像的边缘会变得混乱(可能是因为高斯滤波函数进行卷积,卷积在边缘附近变得奇怪)。那么,有没有更好的办法 示例代码:在python中自动删除图像中的热/死像素,python,image-processing,numpy,camera,scipy,Python,Image Processing,Numpy,Camera,Scipy,我正在使用numpy和scipy处理用CCD相机拍摄的大量图像。这些图像有许多热(和死)像素,其值非常大(或很小)。这些会干扰其他图像处理,因此需要将其删除。不幸的是,尽管一些像素停留在0或255,并且在所有图像中始终处于相同的值,但仍有一些像素暂时停留在其他值上几分钟(数据跨越数小时) 我想知道是否有一种方法可以识别(和删除)python中已经实现的热点像素。如果没有,我想知道什么是一个有效的方法来这样做。通过与相邻像素进行比较,热/死像素相对容易识别。我可以看到写一个循环,查看每个像素,将其
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()
将numpy导入为np
将matplotlib.pyplot作为plt导入
导入scipy.ndimage
plt.图(figsize=(8,4))
ax1=plt.子批次(121)
ax2=plt.子批次(122)
#制作一个样本图像
x=np.linspace(-5,5200)
十、 Y=np.meshgrid(X,X)
Z=255*np.cos(np.sqrt(x**2+Y**2))**2
对于范围(0,11)内的i:
#添加一些热像素
Z[np.random.randint(低=0,高=199),np.random.randint(低=0,高=199)]=np.random.randint(低=200,高=255)
#和死像素
Z[np.random.randint(低=0,高=199),np.random.randint(低=0,高=199)]=np.random.randint(低=0,高=10)
#然后画出来
ax1.set_title('具有热像素的原始数据')
ax1.imshow(Z,插值='最近',原点='较低')
#现在,我们试图找到热点像素
模糊的高斯滤波器(Z,sigma=2)
差=Z-模糊
ax2.set_title('与识别的热像素的差异')
ax2.imshow(差分、插值=‘最近’、原点=‘较低’)
阈值=15
热像素=np。非零((差异>阈值)|(差异基本上,我认为处理热像素的最快方法就是使用大小=2的中值滤波器。然后,噗,你的热像素消失了,你还消除了相机中的其他各种高频传感器噪声
如果你真的只想删除热像素,那么替换你可以从原始图像中减去中值滤波器,就像我在问题中所做的那样,然后用中值滤波图像中的值只替换这些值。这在边缘不起作用,因此如果你可以忽略边缘的像素,那么这将使事情变得复杂容易多了
如果要处理边缘,可以使用下面的代码。但是,它不是最快的:
import numpy as np
import matplotlib.pyplot as plt
import scipy.ndimage
plt.figure(figsize=(10,5))
ax1 = plt.subplot(121)
ax2 = plt.subplot(122)
#make some sample data
x = np.linspace(-5,5,200)
X,Y = np.meshgrid(x,x)
Z = 100*np.cos(np.sqrt(x**2 + Y**2))**2 + 50
np.random.seed(1)
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)
#And some hot pixels in the corners and edges
Z[0,0] =255
Z[-1,-1] =255
Z[-1,0] =255
Z[0,-1] =255
Z[0,100] =255
Z[-1,100]=255
Z[100,0] =255
Z[100,-1]=255
#Then plot it
ax1.set_title('Raw data with hot pixels')
ax1.imshow(Z,interpolation='nearest',origin='lower')
def find_outlier_pixels(data,tolerance=3,worry_about_edges=True):
#This function finds the hot or dead pixels in a 2D dataset.
#tolerance is the number of standard deviations used to cutoff the hot pixels
#If you want to ignore the edges and greatly speed up the code, then set
#worry_about_edges to False.
#
#The function returns a list of hot pixels and also an image with with hot pixels removed
from scipy.ndimage import median_filter
blurred = median_filter(Z, size=2)
difference = data - blurred
threshold = 10*np.std(difference)
#find the hot pixels, but ignore the edges
hot_pixels = np.nonzero((np.abs(difference[1:-1,1:-1])>threshold) )
hot_pixels = np.array(hot_pixels) + 1 #because we ignored the first row and first column
fixed_image = np.copy(data) #This is the image with the hot pixels removed
for y,x in zip(hot_pixels[0],hot_pixels[1]):
fixed_image[y,x]=blurred[y,x]
if worry_about_edges == True:
height,width = np.shape(data)
###Now get the pixels on the edges (but not the corners)###
#left and right sides
for index in range(1,height-1):
#left side:
med = np.median(data[index-1:index+2,0:2])
diff = np.abs(data[index,0] - med)
if diff>threshold:
hot_pixels = np.hstack(( hot_pixels, [[index],[0]] ))
fixed_image[index,0] = med
#right side:
med = np.median(data[index-1:index+2,-2:])
diff = np.abs(data[index,-1] - med)
if diff>threshold:
hot_pixels = np.hstack(( hot_pixels, [[index],[width-1]] ))
fixed_image[index,-1] = med
#Then the top and bottom
for index in range(1,width-1):
#bottom:
med = np.median(data[0:2,index-1:index+2])
diff = np.abs(data[0,index] - med)
if diff>threshold:
hot_pixels = np.hstack(( hot_pixels, [[0],[index]] ))
fixed_image[0,index] = med
#top:
med = np.median(data[-2:,index-1:index+2])
diff = np.abs(data[-1,index] - med)
if diff>threshold:
hot_pixels = np.hstack(( hot_pixels, [[height-1],[index]] ))
fixed_image[-1,index] = med
###Then the corners###
#bottom left
med = np.median(data[0:2,0:2])
diff = np.abs(data[0,0] - med)
if diff>threshold:
hot_pixels = np.hstack(( hot_pixels, [[0],[0]] ))
fixed_image[0,0] = med
#bottom right
med = np.median(data[0:2,-2:])
diff = np.abs(data[0,-1] - med)
if diff>threshold:
hot_pixels = np.hstack(( hot_pixels, [[0],[width-1]] ))
fixed_image[0,-1] = med
#top left
med = np.median(data[-2:,0:2])
diff = np.abs(data[-1,0] - med)
if diff>threshold:
hot_pixels = np.hstack(( hot_pixels, [[height-1],[0]] ))
fixed_image[-1,0] = med
#top right
med = np.median(data[-2:,-2:])
diff = np.abs(data[-1,-1] - med)
if diff>threshold:
hot_pixels = np.hstack(( hot_pixels, [[height-1],[width-1]] ))
fixed_image[-1,-1] = med
return hot_pixels,fixed_image
hot_pixels,fixed_image = find_outlier_pixels(Z)
for y,x in zip(hot_pixels[0],hot_pixels[1]):
ax1.plot(x,y,'ro',mfc='none',mec='r',ms=10)
ax1.set_xlim(0,200)
ax1.set_ylim(0,200)
ax2.set_title('Image with hot pixels removed')
ax2.imshow(fixed_image,interpolation='nearest',origin='lower',clim=(0,255))
plt.show()
输出:
尝试一种更简单的情况:使用中值滤波(例如,通过3x3模式)生成另一幅图像,并计算图像与滤波图像之间差值的绝对值。将原始图像的像素替换为该差值的较大值(例如,100)通过过滤值。阈值的值可以通过差异统计自动获得。@Eddy_Em,感谢您建议使用中值滤波器-这似乎比高斯滤波器更好。此外,我喜欢使用差异数组的统计信息设置阈值的想法。我试着取标准差,这是eemed工作正常。(我将阈值设置为标准偏差的5倍。)但是,我对你的建议感到困惑,你建议将差分数组的倍数添加到图像数组中。这有什么作用?哦,不:我只是说你搜索像素,通过一些阈值在差分数组中进行清理。好的,这就是我现在正在做的。这似乎与中值滤波器配合得很好。仍然存在边缘效应中值滤波器在边缘附近产生不同的结果,因此它使那里看起来有很多热像素。知道如何使它在边缘附近工作吗?目前,我只是忽略边缘,但这似乎是一个不雅观的解决方案。好问题!有很多天文学策略可用,例如,你能使用边缘mi吗此处出错,以避免复杂的棱角处理?即:模糊=中值滤波器(图像数据,大小=2,mode=“mirror”)