如何在二值图像中找到像素簇的质心

时间:2019-05-06 12:52:43

标签: matlab image-processing centroid

我已经在MATLAB中编写了一些代码,该代码使用设置的阈值将(恒星)图像转换为二进制图像,然后标记高于此阈值的每个像素(恒星)簇。标签产生输出: 例如

import tkinter as tk
from tkinter import *
import random
import re
import datetime
from tkinter import messagebox
from tkinter.font import Font
root = tk.Tk()
root.title('deneme')
root.geometry('410x600+400+100')
root.config(bg='lightblue')
buton_işlevi=StringVar(root)
buton_işlevi.set("")


#buton oluşturma ve konumu
buton = tk.Button(root, width=10, height=2, relief='raised',state='active',command=lambda :add_text(pencere,giriş,buton_işlevi))
buton.pack()
buton.place(x=310, y=550)
buton.config(text='GÖNDER', bg='lightblue', font='Verdana 8 bold')
root.bind('<Return>',lambda x:add_text(pencere,giriş,buton_işlevi))

#mesaj yazma alanı ve konumu
giriş = tk.Entry(root, textvariable=buton_işlevi,font=('NanumGothic', 12)) 
giriş.pack()
giriş.place(x=10, y=550, width=290, height=40)

canvas = Canvas(width=300, height=300, bg='white')
canvas.create_oval(200, 200, 300, 300, width=5, fill='red')

#pencere ve konumu
pencere = tk.Text(root, bg='white', yscrollcommand='YES', font=('NanumGothic', 12))
pencere.config(state='disabled')
pencere.pack()
pencere.place(x=10, y=10, width=390, height=530)      


#bot ve user mesaj arka plan rengi
pencere.tag_config('bot_renk', background='#fccbc7', foreground='black')
pencere.tag_config('user_renk', background='yellow')
pencere.config(state='normal')

#bot karşılama mesajı
karşılama = 'Hoşgeldiniz'
soru1  = ['merhaba', 'selam']
cevap1 = ["sanada", "iyiyim"]
soru2  = ["deneme", "merhaba", "selam"]

pencere.insert('end', '\nBOT:\t')
pencere.insert('end', karşılama +'\n', 'bot_renk')


#Mesaj ayarları
def add_text(mw,st,imsg):
#mw:message window/st:state/imsg:input message
    bot_mesaj=""
    user_mesaj = imsg.get()

    if user_mesaj in soru1:
        user_mesaj='\nUSER :\t'+imsg.get()+'\n'+canvas
        bot_mesaj = '\nBOT  :\t'+ random.choice(cevap1)+'\n'
        mw.config(state='normal')        
        mw.insert('end',user_mesaj, 'user_renk')
        mw.insert('end',bot_mesaj, 'bot_renk')
        imsg.set("")
        mw.see('end')
        mw.config(state='disabled')

    elif user_mesaj in soru2:
        user_mesaj='\nERÇİN   :\t'+imsg.get()+'\n'
        bot_mesaj='\nBOT   :\t'+ random.choice(cevap2)+'\n'
        mw.config(state='normal')               
        mw.insert('end',user_mesaj, 'user_renk')  
        mw.insert('end',bot_mesaj, 'bot_renk')    
        imsg.set("")
        mw.see('end')
        mw.config(state='disabled')

    else :
        user_mesaj='\nUSER:\t' +imsg.get()+'\n'
        bot_mesaj='\nBOT:\t' + 'Bu kelimeyi henüz öğrenmedim' +'\n'
        mw.config(state='normal')
        mw.insert('end',user_mesaj, 'user_renk')
        mw.insert('end',bot_mesaj, 'bot_renk')
        imsg.set("")
        mw.see('end')
        mw.config(state='disabled')

root.mainloop()

因此1、2、3等的每个簇代表一个星星。我使用以下链接提供的答案:How to find all connected components in a binary image in Matlab?标记像素。 我也不能使用图像处理工具箱。 我到目前为止的代码如下所示。

我现在如何找到图像中每个像素簇的质心?

[1 1 1 0 0 0 0 0 0
 1 1 0 0 0 2 2 2 0
 0 0 0 3 3 0 2 0 0
 0 0 0 3 3 0 0 0 0]

1 个答案:

答案 0 :(得分:1)

质心是一阶矩。由

计算
sum(x*v)/sum(v) , sum(y*v)/sum(v)

对于二进制图像,您可以执行此操作(我使用的是平凡的循环,而不是矢量化的代码,因此我们以后可以轻松对其进行扩展):

img = [1 1 1 0 0 0 0 0 0
       1 1 0 0 0 2 2 2 0
       0 0 0 3 3 0 2 0 0
       0 0 0 3 3 0 0 0 0]; % Op's example data

bin = img==1;              % A binary image

% Algorithm
sum_v = 0;
sum_iv = 0;
sum_jv = 0;
for jj=1:size(bin,2)
   for ii=1:size(bin,1)
      sum_v = sum_v + bin(ii,jj);
      sum_iv = sum_iv + ii * bin(ii,jj);
      sum_jv = sum_jv + jj * bin(ii,jj);
   end
end
centroid = [sum_iv, sum_jv] / sum_v;

您当然可以遍历标签图像img的每个标签,然后应用上面的代码。但这是非常低效的。相反,我们可以遍历图像一次,并同时计算所有质心。我们将sum_v等转换为向量,每个标签包含一个运行总和:

N = max(img(:));     % number of labels
sum_v = zeros(N,1);
sum_iv = zeros(N,1);
sum_jv = zeros(N,1);
for jj=1:size(img,2)
   for ii=1:size(img,1)
      index = img(ii,jj);
      if index>0
         sum_v(index) = sum_v(index) + 1;
         sum_iv(index) = sum_iv(index) + ii;
         sum_jv(index) = sum_jv(index) + jj;
      end
   end
end
centroids = [sum_iv, sum_jv] ./ sum_v;