图像测量算法
图像简介
在二值图像中,相互连接的黑像素的集合成为一个黑区域。通过对图像内每个区域进行标记操作,求得区域的数量。每个像素存放的是这个区域的标号,而不是其灰度值。这样的话,只需要统计标号的数量就可以知道其面积。
标记准则
- 从左到右,从上到下逐个像素扫描,且初始标号为0
- 若该点的左上、正上、右上及左前都不为物体,则对标号进行加1操作
- 优先级依次为:右上、正上、左上、左(逐渐递减)
- 如果右上为物体,则当前标记为和右上点相同的值
- 如果右上点不为物体,则判断正上点。
- 如果右上点与左前点标记数不一致,且左前点和正上点都无物体,则用广度优先算法将左前点及其联通点的值都设置为当前标记数
代码实现
class BH(BmpManager):
def recard(self):
img=np.copy(self.Img)
direction=[[1,-1],[0,-1],[-1,-1],[-1,0]]
state=0
recbuf=np.zeros(shape=[self.f_height,self.f_width],dtype=int)
for y in range(1,len(self.Img)):
for x in range(1,len(self.Img[y])):
if self.Img[y,x,0]!=0:
continue
flag=False
for dir in direction:
c_x,c_y=x+dir[0],y+dir[1]
if recbuf[c_y][c_x]==0:
continue
if flag==False :
recbuf[y][x]=recbuf[c_y][c_x]
flag=True
elif flag==True and recbuf[y-1][x]==0 and recbuf[y-1][x-1]==0:
init_v=recbuf[y][x]
stack=[]
stack.append((c_x,c_y))
while len(stack)>0:
n_x,n_y=stack.pop(-1)
if recbuf[n_y][n_x]!=0 and recbuf[n_y][n_x]!=init_v:
recbuf[n_y][n_x]=init_v
for dir in direction:
if recbuf[n_y+dir[1]][n_x+dir[0]]!=0 and recbuf[n_y+dir[1]][n_x+dir[0]]!=init_v:
stack.append((n_x+dir[0],n_y+dir[1]))
if recbuf[y][x]==0:
state=state+1
recbuf[y][x]=state
count=0
Nutil = NumberImg()
for i in range(1,state+1):
x=np.sum(recbuf==i)
if x<100:
continue
count=count+1
y_axis,x_axis=np.where(recbuf==i)
X=int((x_axis[0]+x_axis[-1])/2)
Y=int((y_axis[0]+y_axis[-1])/2)
num_img=Nutil.getNumberImg(str(count))
for num_x in range(X,X+len(num_img[0])):
for num_y in range(Y,Y+len(num_img)):
if num_img[num_y-Y,num_x-X][0]==255:
num_img[num_y-Y,num_x-X,:]=img[num_y,num_x,:]
else:
num_img[num_y - Y, num_x - X, :]=255-num_img[num_y-Y,num_x-X,:]
img[Y:Y+len(num_img),X:X+len(num_img[0]),:]=num_img
self.Img=img
class NumberImg:
def __init__(self):
bm=BmpManager('')
bm.Parse('数字.bmp')
img=bm.Img
last_x=-1
count=0
self.arr={}
for x in range(0, bm.f_width):
flag=False
for y in range(0, bm.f_height):
if img[y,x,0]==0:
flag=True
break
if flag==False and last_x!=-1:
count=count+1
img_temp=img[:,last_x-2:x+5,:]
self.arr[str(count)]=img_temp
last_x=-1
if flag==True and last_x==-1:
last_x=x
def getNumberImg(self,i):
res=None
for n in i:
if res is None:
res=self.arr[n]
else:
print(self.arr[n].shape)
res=np.hstack([res,self.arr[n]])
return res
原图如下
效果图如下
可以看到,上述算法,找到了图中有多少物体,并且把物理给标记了数字。这些数字都是算法生成的