嵌入式上位机图像分割心得

今天老师临时交给我的任务,本来需要在下位机完成,但是由于希望加快速度,就把比较耗时的分割步骤放在上位机进行处理。

进行图像分割我采用的是twopass方法,具体算法的细节部分大家可以百度一下。

因为是图片处理,建议大家最好不要使用不同的图片处理模块在一个程序当中,那样很容易造成混乱。

首先肯定是需要读取图片,我整个程序采用PIL包。并且在这里分享一个具体介绍PIL的一个博客:https://www.cnblogs.com/meitian/p/3699223.html

在使用twopass算法之前,有两个很关键的函数需要去定义的,一个是寻找根节点的函数,一个是把我们的区域连通起来的函数:

#寻找根节点
def find_root(label):
    label = int(label)
    while Parent[label] != 0:
        label = Parent[label]
    return label


#将不同label合并到一个联通域
def union_label(label1,label2):
    label1 = int(label1)
    label2 = int(label2)
    while Parent[label1] != 0:
        label1 = Parent[label1]
    while Parent[label2] != 0:
        label2 = Parent[label2]
    if label1 != label2:
        Parent[label1] = label2

按照twopass算法,我们需要遍历图片的每一个像素,寻找符合我们要求的像素点,然后给他一个标签,遍历像素点我用了load方法,读取了rgb的数值,最后我转化为了hsv,hsv更方便我们处理。

im = Image.open(r"C:\Users\Administrator\Desktop\JPEG\001.jpg")
pix = im.load()
width = im.size[0]
height = im.size[1]
for y in range(height):
    for x in range(width):
        r,g,b = pix[x, y]
        h,s,v = rgb2hsv(r,g,b)

 

然后我们设定一个hsv的范围,就是寻找符合我们要求的像素点进行处理,我的方法就是使用画图测出来的。

然后我们就开始我们的twopass啦,首先当然是firstpass:

if h >= condition[0] and h <= condition[1] and s >= condition[2] and s <= condition[3] and v >= condition[4] and v <= condition[5]:
            if x == 0 and y == 0:
                labelcount += 1
                label[x][y] = labelcount 
            elif y == 0:
                if label[x-1][y] > 0:
                    label[x][y] = label[x-1][y]
                else:
                    labelcount += 1
                    label[x][y] = labelcount 
            elif x == 0:
                if label[x][y-1] > 0:
                    label[x][y] = label[x][y-1]
                else:
                    labelcount += 1
                    label[x][y] = labelcount 
            else:
                if label[x-1][y] > 0 and label[x][y-1] > 0:
                    if label[x-1][y] != label[x][y-1]:
                        label[x][y] = min(label[x-1][y],label[x][y-1])
                        union_label(max(label[x-1][y],label[x][y-1]),label[x][y])
                    else:
                        label[x][y] = label[x-1][y]
                elif label[x-1][y] > 0:
                    label[x][y] = label[x-1][y] 
                elif label[x][y-1] > 0:
                    label[x][y] = label[x][y-1] 
                else:
                    labelcount += 1
                    label[x][y] = labelcount 
        else :
            label[x][y] = 0

中间的labelcount初始化是0,是我们的标签,不符合我们要求的像素点都还是0,这样我们的第一步就完成了啊。

接下来就是secondpass啦,进行根节点的一个统计,把我们最多的根节点统计下来,最终得到我们最多的根节点,根据最多的根节点来进行分割:

#Second pass 
for y in range(height):              
    for x in range(width):
        label[x][y] = find_root(label[x][y])
        if label[x][y] > 0:#因为我们不要的标签都定义为0,把我们不需要的都排除掉
            labelsize[int(label[x][y])] += 1
            
#寻找最大连通区域标号
max_sum = max(labelsize)
max_label = labelsize.index(max_sum) 

之后就可以根据标签来寻找分割区域的坐标啦:

#标记区域范围
xmin = 240
ymin = 320
xmax = 0
ymax = 0
for y in range(height):
    for x in range(width):
        if label[x][y] == max_label:
            if x < xmin:
                xmin = x
            if y < ymin:
                ymin = y
            if x > xmax:
                xmax = x
            if y > ymax:
                ymax = y

然后我画分割线的时候并没有使用什么模块,我是直接改变了像素值达到了画线的目的:

for i in range(xmin,xmax):
    im.putpixel((i,ymin),(0,255,0))
for i in range(xmin,xmax):
    im.putpixel((i,ymax),(0,255,0))
for i in range(ymin,ymax):
    im.putpixel((xmin,i),(0,255,0))
for i in range(ymin,ymax):
    im.putpixel((xmax,i),(0,255,0))

最后我们再show一下就出来啦。

附上整个过程的代码:

import numpy as np
from PIL import Image
condition = [195,220,0.2,1.0,0.5,1.0]
labelcount = 0
label = np.zeros((320,240))
Parent = [0]*1000
labelsize = [0]*1000

def rgb2hsv(r, g, b):
    r, g, b = r/255.0, g/255.0, b/255.0
    mx = max(r, g, b)
    mn = min(r, g, b)
    m = mx-mn
    if mx == mn:
        h = 0
    elif mx == r:
        if g >= b:
            h = ((g-b)/m)*60
        else:
            h = ((g-b)/m)*60 + 360
    elif mx == g:
        h = ((b-r)/m)*60 + 120
    elif mx == b:
        h = ((r-g)/m)*60 + 240
    if mx == 0:
        s = 0
    else:
        s = m/mx
    v = mx
    return h, s, v

#寻找根节点
def find_root(label):
    label = int(label)
    while Parent[label] != 0:
        label = Parent[label]
    return label


#将不同label合并到一个联通域
def union_label(label1,label2):
    label1 = int(label1)
    label2 = int(label2)
    while Parent[label1] != 0:
        label1 = Parent[label1]
    while Parent[label2] != 0:
        label2 = Parent[label2]
    if label1 != label2:
        Parent[label1] = label2



#main
im = Image.open(r"C:\Users\Administrator\Desktop\JPEG\001.jpg")
pix = im.load()
width = im.size[0]
height = im.size[1]
for y in range(height):
    for x in range(width):
        r,g,b = pix[x, y]
        h,s,v = rgb2hsv(r,g,b)
        
#First pass
        if h >= condition[0] and h <= condition[1] and s >= condition[2] and s <= condition[3] and v >= condition[4] and v <= condition[5]:
            if x == 0 and y == 0:
                labelcount += 1
                label[x][y] = labelcount 
            elif y == 0:
                if label[x-1][y] > 0:
                    label[x][y] = label[x-1][y]
                else:
                    labelcount += 1
                    label[x][y] = labelcount 
            elif x == 0:
                if label[x][y-1] > 0:
                    label[x][y] = label[x][y-1]
                else:
                    labelcount += 1
                    label[x][y] = labelcount 
            else:
                if label[x-1][y] > 0 and label[x][y-1] > 0:
                    if label[x-1][y] != label[x][y-1]:
                        label[x][y] = min(label[x-1][y],label[x][y-1])
                        union_label(max(label[x-1][y],label[x][y-1]),label[x][y])
                    else:
                        label[x][y] = label[x-1][y]
                elif label[x-1][y] > 0:
                    label[x][y] = label[x-1][y] 
                elif label[x][y-1] > 0:
                    label[x][y] = label[x][y-1] 
                else:
                    labelcount += 1
                    label[x][y] = labelcount 
        else :
            label[x][y] = 0
#Second pass 
for y in range(height):              
    for x in range(width):
        label[x][y] = find_root(label[x][y])
        if label[x][y] > 0:
            labelsize[int(label[x][y])] += 1
            
#寻找最大连通区域标号
#max_sum = max(labelsize)#去掉最多的白色和红色
#labelsize.remove(max_sum)
max_sum = max(labelsize)#拿出次多的蓝色
max_label = labelsize.index(max_sum) #前面删除一个所以要加一
#标记区域范围
xmin = 240
ymin = 320
xmax = 0
ymax = 0
for y in range(height):
    for x in range(width):
        if label[x][y] == max_label:
            if x < xmin:
                xmin = x
            if y < ymin:
                ymin = y
            if x > xmax:
                xmax = x
            if y > ymax:
                ymax = y

for i in range(xmin,xmax):
    im.putpixel((i,ymin),(0,255,0))
for i in range(xmin,xmax):
    im.putpixel((i,ymax),(0,255,0))
for i in range(ymin,ymax):
    im.putpixel((xmin,i),(0,255,0))
for i in range(ymin,ymax):
    im.putpixel((xmax,i),(0,255,0))
im.show()

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值