2015-05-06 98 views
4

這裏是種圖像的,我會處理的例子:如何找到圖像中亮點的中心?

Balls http://pages.cs.wisc.edu/~csverma/CS766_09/Stereo/callight.jpg

其中,在每一球的一個大亮點。我想找到亮點中心的座標。我怎樣才能在Python或Matlab中做到這一點?我現在遇到的問題是,現場不止一個點具有相同(或大致相同)的白色,但我需要的是找到這個「白色點」的中心。

另外,對於最左側和最右側的圖像,我怎樣才能找到整個圓形物體的中心?

+0

用二維圓形掩模卷繞(例如高斯)並查找給出最大相關性的掩模座標? –

+2

爲什麼不簡單地取圖像亮度的百分之95的像素的平均座標?當存在多個亮點時,這不起作用,但對於單點而言,這應該會給你最簡單的解決方案。 – knedlsepp

+0

您也可以轉換爲灰度閾值,並查找閾值結果的平均座標。無需過濾。 – rayryeng

回答

7

您可以簡單地對圖像進行閾值並找到剩餘的平均座標。當有多個具有相同強度的值時,這將處理這種情況。當您對圖像進行閾值處理時,顯然會有多個亮白色像素,因此如果要將它們放在一起,請找到質心或座標以確定所有這些白色亮像素的中心。在這種特殊情況下不需要過濾。這裏有一些與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   

我得到這個:

enter image description here


如果你想要一個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() 

我們得到這個數字:

enter image description here

小阿里納斯

我可以完全跳過上面的代碼和使用regionpropsMATLAB link,scikit-image link)。您可以簡單地對圖像進行閾值處理,然後應用regionprops來查找每個白色像素羣的質心,但是我認爲我會向您展示更爲手動的方式,以便您可以欣賞算法並自行理解它。


希望這有助於!

+0

好的完整答案。由於找到正確的閾值(這裏是200/255)可能會很棘手,所以我建議應用非線性凹函數(如我在我的回答中解釋的'exp'或_gamma correction_操作)非常重要,因爲它會加劇最亮點甚至更多。它使檢測更加健壯。在任何情況下都可以使用直方圖來自動找到正確的閾值;例如通過找出所有像素中1%(以百分位數)最亮像素的值。 –

+0

@SohailSi像大津這樣的東西可以工作,根據您的建議評估直方圖。應用非線性濾波器也是一個好主意,但我會將其留給OP。我覺得我已經做了足夠的一個職位! – rayryeng

1

使用2D卷積,然後找到最高強度的點。在應用2d卷積之前,可以在強度值上應用凹非線性函數(如exp),以增強亮點相對於圖像的調光部分的亮度。類似於conv2(exp(img),ker)