如何从噪声背景中提取白色斑点?

时间:2017-07-01 18:06:45

标签: python opencv image-processing computer-vision

我有一个像这样的图像:

Noisy image

如你所见,它非常嘈杂。我想提取白色斑点的坐标及其信噪比(斑点与噪声的区别)。

我应该以哪种方式解决这个问题?我可以使用现有的算法吗?

请注意我知道如何在轮廓上提取斑点的坐标以及如何对图像进行去噪,但在这种情况下噪点非常强烈,我无法使其正常工作。 此外,如果它有帮助,我可以使用不同噪声的相同斑点多次拍摄,但我不能平均随着时间的推移相对于彼此的斑点移动。

4 个答案:

答案 0 :(得分:3)

我认为@WillHeitman提出的形态开放给出了一个很好的起点。我刚刚在命令行中使用 ImageMagick

执行此操作
convert noise.png -threshold 80% -morphology open diamond result.png

enter image description here

答案 1 :(得分:2)

如果你想要一个快速而肮脏的解决方案,你可以尝试侵蚀然后扩张。侵蚀将移除较小的碎片,并且扩张将恢复较大的块。修改参数应该得到您正在寻找的结果。之后,您的图像应该被去噪,此时您可以从轮廓斑点中提取出坐标。希望这有帮助!

答案 2 :(得分:2)

这是使用连接组件在ImageMagick中处理此问题的另一种方法。首先,我将图像模糊一点,然后是阈值。然后扔掉面积小于10像素的区域。连接的组件告诉我边界框,质心,区域和颜色。

convert input.png -blur 0x1 -threshold 85% -type bilevel +write tmp1.png -define connected-components:verbose=true -define connected-components:area-threshold=10 -define connected-components:mean-color=true -connected-components 8 objects.gif

这是tmp1.png图像,用于查看阈值的含义:

thresholdd result

以下是连接组件的结果:

connected components result

以下是有关地区的信息:

Objects (id: bounding-box centroid area mean-color):
  0: 254x158+0+0 125.9,78.8 39619 gray(0)
  6: 18x17+205+34 213.6,42.3 241 gray(255)
  14: 12x12+229+91 234.6,97.0 108 gray(255)
  1: 12x10+32+0 37.7,4.0 63 gray(255)
  5: 4x5+11+19 12.4,20.9 17 gray(255)
  16: 6x4+19+106 21.4,107.8 17 gray(255)
  18: 4x6+194+116 195.5,118.5 17 gray(255)
  8: 4x5+242+56 243.8,58.2 16 gray(255)
  12: 3x5+68+82 69.0,83.8 12 gray(255)
  17: 4x4+182+109 183.6,110.8 12 gray(255)

其中灰色(0)为黑色,灰色(255)为白色。

现在,如果您想知道输入图像中除这些区域之外的平均背景,您可以这样做:

convert input.png \( objects.gif -negate \) -alpha off -compose copy_opacity -composite -scale 1x1! -format "%[fx:255*u]\n" info:

返回:160.105,范围为0到255.在ImageMagick中,如果您将对1像素透明的图像缩放并获取其值,则ImageMagick会在-scale函数中执行平均值,忽略透明像素。所以我使用二进制的objects.gif作为掩码,将其反转(否定)放入输入图像的alpha通道,以从平均值中排除掩码区域。

现在,如果您想获得每个区域的平均颜色,然后获得信噪比的一些测量值,您可以获得区域颜色与背景颜色的比率,并将其表示为百分比。请注意,我使用输出图像中区域的边界框作为输入图像中区域的边界框的Alpha通道,以获得区域的平均颜色。然后将该比率与平均背景颜色进行比较并转换为百分比。 (Unix语法)

OFS=$IFS
IFS=$'\n'
arr=(`convert input.png -blur 0x1 +write tmp1.png -threshold 85% -type bilevel +write tmp2.png \
-define connected-components:verbose=true \
-define connected-components:area-threshold=10 \
-define connected-components:mean-color=true \
-connected-components 8 tmp3.png | sed 's/^[ ]*//' | tail -n +3`)
bckavg=`convert input.png \( tmp3.png -negate \) -alpha off -compose copy_opacity -composite -scale 1x1! -format "%[fx:u]" info:`
num=${#arr[*]}
for ((i=0; i<num; i++)); do
bbox=`echo "${arr[$i]}" | cut -d\  -f2`
cent=`echo "${arr[$i]}" | cut -d\  -f3`
area=`echo "${arr[$i]}" | cut -d\  -f4`
snr=`convert input.png[$bbox] tmp3.png[$bbox] -alpha off -compose copy_opacity -composite -scale 1x1! -format "%[fx:100*u/$bckavg]\n" info:`
echo "centroid=$cent area=$area snr=$snr%"
done
IFS=$OFS

哪个列表:

centroid=213.6,42.3 area=241 snr=156.745%
centroid=234.6,97.0 area=108 snr=155.258%
centroid=37.7,4.0 area=63 snr=152.072%
centroid=12.4,20.9 area=17 snr=153.319%
centroid=21.4,107.8 area=17 snr=149.644%
centroid=195.5,118.5 area=17 snr=151.63%
centroid=243.8,58.2 area=16 snr=154.235%
centroid=69.0,83.8 area=12 snr=152.555%
centroid=183.6,110.8 area=12 snr=153.076%

或者您可以将(功率)信号表示为分贝噪声:

OFS=$IFS
IFS=$'\n'
arr=(`convert input.png -blur 0x1 +write tmp1.png -threshold 85% -type bilevel +write tmp2.png \
-define connected-components:verbose=true \
-define connected-components:area-threshold=10 \
-define connected-components:mean-color=true \
-connected-components 8 tmp3.png | sed 's/^[ ]*//' | tail -n +3`)
bckavg=`convert input.png \( tmp3.png -negate \) -alpha off -compose copy_opacity -composite -scale 1x1! -format "%[fx:u]" info:`
num=${#arr[*]}
for ((i=0; i<num; i++)); do
bbox=`echo "${arr[$i]}" | cut -d\  -f2`
cent=`echo "${arr[$i]}" | cut -d\  -f3`
area=`echo "${arr[$i]}" | cut -d\  -f4`
snr=`convert input.png[$bbox] tmp3.png[$bbox] -alpha off -compose copy_opacity -composite -scale 1x1! -format "%[fx:10*log((u/$bckavg)*(u/$bckavg))]\n" info:`
echo "centroid=$cent area=$area snr=$snr db"
done
IFS=$OFS

哪个列表:

centroid=213.6,42.3 area=241 snr=3.90389 db
centroid=234.6,97.0 area=108 snr=3.82108 db
centroid=37.7,4.0 area=63 snr=3.64098 db
centroid=12.4,20.9 area=17 snr=3.7119 db
centroid=21.4,107.8 area=17 snr=3.50118 db
centroid=195.5,118.5 area=17 snr=3.61568 db
centroid=243.8,58.2 area=16 snr=3.76365 db
centroid=69.0,83.8 area=12 snr=3.66856 db
centroid=183.6,110.8 area=12 snr=3.69812 db

编辑:这是一个稍微高效的版本,不需要边界框处理。它通过向流程添加-fuzz直接获得区域的平均颜色。

OFS=$IFS
IFS=$'\n'
arr=(`convert input.png -blur 0x1 +write tmp1.png -black-threshold 85% +write tmp2.png \
\( -clone 0 -threshold 0 +write tmp3.png +delete \) \
-fuzz 15% \
-define connected-components:verbose=true \
-define connected-components:area-threshold=10 \
-define connected-components:mean-color=true \
-connected-components 8 tmp3.png | sed 's/^[ ]*//' | tail -n +3`)
bckavg=`convert input.png \( tmp3.png -negate \) -alpha off -compose copy_opacity -composite -scale 1x1! -format "%[fx:255*u]" info:`
echo "bckavg=$bckavg"
num=${#arr[*]}
for ((i=0; i<num; i++)); do
cent=`echo "${arr[$i]}" | cut -d\  -f3`
area=`echo "${arr[$i]}" | cut -d\  -f4`
graylevel=`echo "${arr[$i]}" | sed -n 's/^.*gray[(]\([0-9]*\)[)]$/\1/p'`
snr=`convert xc: -format "%[fx:10*log(($graylevel/$bckavg)*($graylevel/$bckavg))]\n" info:`
echo "centroid=$cent area=$area graylevel=$graylevel snr=$snr db"
done
IFS=$OFS

以下是列表:

centroid=213.6,42.3 area=241 graylevel=246 snr=3.72702 db
centroid=234.6,97.0 area=108 graylevel=242 snr=3.58463 db
centroid=37.7,4.0 area=63 graylevel=235 snr=3.32968 db
centroid=12.4,20.9 area=17 graylevel=231 snr=3.18056 db
centroid=21.4,107.8 area=17 graylevel=228 snr=3.06702 db
centroid=195.5,118.5 area=17 graylevel=227 snr=3.02884 db
centroid=243.8,58.2 area=16 graylevel=227 snr=3.02884 db
centroid=69.0,83.8 area=12 graylevel=222 snr=2.83538 db
centroid=183.6,110.8 area=12 graylevel=228 snr=3.06702 db

snr的结果值略有不同。

答案 3 :(得分:1)

我喜欢@Setchell的答案,但您对获得信噪比(SNR)的愿望很感兴趣

我认为第一步是定义完美信号。然后,您可以将该完美信号与您的数据进行比较。

例如,我将一个完美信号定义为高斯矩阵,其sigma = 1,其尺寸与您的图像相匹配。

enter image description here

然后在原始图片和完美信号之间执行phase correlation 。相位相关算法大致是:

  1. 采用原始图像的傅立叶变换(fft)
  2. 取第二张图像(完美斑点)的fft的共轭
  3. 乘以(1)和(2)
  4. 的结果
  5. 取结果(3)的逆fft
  6. 步骤(4)的结果如下图所示。

    enter image description here

    好吧,我知道它看起来并不好但是很酷的是相位相关结果的值是有效的coherence值,它们告诉你原始图像与完美图像的相似程度图像。值1是完美匹配,而值-1是完美不匹配。

    从这里你可以做一些很酷的技巧,比如找不到点/像素,但找到具有最高相干值的区域/区域。

    如果我的回答令人困惑或您有任何疑问,请告诉我们!祝好运!