【问题标题】:how to locate the center of a bright spot in an image?如何定位图像中亮点的中心?
【发布时间】:2015-07-16 21:13:25
【问题描述】:

这是我将要处理的图像类型的示例:


(来源:csverma at pages.cs.wisc.edu

每个球上都有一个亮点。我想定位亮点中心的坐标。我怎样才能在 Python 或 Matlab 中做到这一点?我现在遇到的问题是,现场不止一个点具有相同(或大致相同)的白色,但我需要找到这个“集群”白点的中心。

另外,对于最左边和最右边的图像,如何找到整个圆形物体的中心?

【问题讨论】:

  • 与 2D 圆形掩模(例如高斯)卷积并找到相关性最大的掩模坐标?
  • 为什么不简单地取图片亮度 95% 内的像素的平均坐标呢?当有多个亮点时,这将不起作用,但对于单个亮点,这应该为您提供最简单的解决方案。
  • 您还可以转换为灰度,阈值并找到阈值结果的平均坐标。无需过滤。
  • @bla - 哦,是的。漂亮的代码。

标签: python image matlab search image-processing


【解决方案1】:

您可以简单地对图像设置阈值并找到剩余部分的平均坐标。当有多个值具有相同的强度时,这将处理这种情况。当你对图像进行阈值处理时,显然会有不止一个明亮的白色像素,所以如果你想把它们放在一起,找到质心或平均坐标来确定所有这些白色的中心明亮的像素。在这种特殊情况下不需要过滤。这是 MATLAB 中的一些内容。

我直接读取了该图像,将其转换为灰度并清除了每个图像周围的白色边框。接下来,我将图像分成 5 个块,对图像进行阈值处理,找到剩余的平均坐标,并在每个中心所在的位置放置一个点:

im = imread('http://pages.cs.wisc.edu/~csverma/CS766_09/Stereo/callight.jpg');
im = rgb2gray(im);
im = imclearborder(im);

%// Split up images and place into individual cells
split_point = floor(size(im,2) / 5);
images = mat2cell(im, size(im,1), split_point*ones(5,1));

%// Show image to place dots
imshow(im);
hold on;

%// For each image...
for idx = 1 : 5
    %// Get image
    img = images{idx}; 

    %// Threshold
    thresh = img > 200;

    %// Find coordinates of thresholded image
    [y,x] = find(thresh);

    %// Find average
    xmean = mean(x);
    ymean = mean(y);

    %// Place dot at centre
    %// Make sure you offset by the right number of columns
    plot(xmean + (idx-1)*split_point, ymean, 'r.', 'MarkerSize', 18);
end        

我明白了:


如果您需要 Python 解决方案,我建议使用 scikit-image 结合 numpymatplotlib 进行绘图。这是上面用 Python 转录的代码。请注意,我将链接引用的图像手动保存在磁盘上并将其命名为balls.jpg

import skimage.io
import skimage.segmentation
import numpy as np
import matplotlib.pyplot as plt

# Read in the image
# Note - intensities are floating point from [0,1]
im = skimage.io.imread('balls.jpg', True)

# Threshold the image first then clear the border
im_clear = skimage.segmentation.clear_border(im > (200.0/255.0))

# Determine where to split up the image
split_point = int(im.shape[1]/5)

# Show image in figure and hold to place dots in
plt.figure()
plt.imshow(np.dstack([im,im,im]))

# For each image...
for idx in range(5):

  # Extract sub image
  img = im_clear[:,idx*split_point:(idx+1)*split_point]

  # Find coordinates of thresholded image
  y,x = np.nonzero(img)

  # Find average
  xmean = x.mean()
  ymean = y.mean()

  # Plot on figure
  plt.plot(xmean + idx*split_point, ymean, 'r.', markersize=14)

# Show image and make sure axis is removed
plt.axis('off')
plt.show()

我们得到这个数字:

小旁注

我本可以完全跳过上面的代码并使用regionpropsMATLAB linkscikit-image link)。您可以简单地对图像进行阈值处理,然后应用 regionprops 来查找每个白色像素簇的质心,但我想我会向您展示一种更手动的方法,以便您可以欣赏算法并自己理解它。


希望这会有所帮助!

【讨论】:

  • 很好的完整答案。由于找到正确的阈值(此处为 200/255)可能很棘手,我建议应用非线性凹函数(如我在回答中解释的 expgamma 校正 操作) 很重要,因为它更加突出了最亮的点。它使检测更加稳健。在任何情况下,也可以使用直方图自动找到正确的阈值;例如通过查找所有像素中最亮的 1%(以百分位数表示)像素的值。
  • @SohailSi 像 Otsu 这样的东西可以按照您的建议评估直方图。应用非线性过滤器也是一个好主意,但我将把它留给 OP。我想我已经为一个帖子做的足够了!
【解决方案2】:

使用 2D 卷积,然后找到强度最高的点。您可以在应用 2d 卷积之前对强度值应用凹非线性函数(例如 exp),以增强相对于图像较暗部分的亮点。类似conv2(exp(img),ker)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-12
    • 2011-04-05
    • 2014-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-06
    • 2012-12-10
    相关资源
    最近更新 更多