这篇文章主要介绍了Python计算不规则图形面积算法实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
介绍:大三上做一个医学影像识别的项目,医生在原图上用红笔标记病灶点,通过记录红色的坐标位置可以得到病灶点的外接矩形,但是后续会涉及到红圈内的面积在外接矩形下的占比问题,有些外接矩形内有多个红色标记,在使用网上的opencv的fillPoly填充效果非常不理想,还有类似python计算任意多边形方法也不理想的情况下,自己探索出的一种效果还不错的计算多圈及不规则图形的面积的算法。
能较为准确的计算出不规则图形的面积
正文:算法的思想很简单,遍历图片每一列,通过色差判断是否遇到标记圈,将坐标全部记录,对每一列的坐标都进行最小行和最大行记录,确定每一列的最小和最大的坐标,然后上色(类似opencv的fillPoly的实现,但是细节有些区别),只是这样效果并不好,将图片旋转90度,再做一边,将两个图片的结果放在一起做与操作,得到结果就能很好的处理多圈的标记问题和多算面积的问题(比如上面的08-LM),
算法实现
全程只用pillow库
首先先用屏幕拾色器获取目标颜色的rgb值,我这种情况下就是(237,28,36),前期截取外接矩形也是要这一步的,颜色也一致
def pixel_wanted(pix): return pix==(237,28, 36)
每一列都设定翻转位初始为False,如果上一个像素点不是目标色,当前是目标色则开始记录,一旦不是目标色,停止检测
top_Pixel都设定为黑色(0,0,0)因为有图片最上方就是目标色,导致判定出问题,直接让最上面的像素初始化是黑色
coordinate_List记录了所有符合的点坐标
coordinate_List = [] top_Pixel = (0,0,0) for x in range(im.size[0]): flag = False #初始化每一列翻转位为False for y in range(im.size[1]): current_pixel = im.getpixel((x,y)) last_pixel = im.getpixel((x,y-1)) if y>0 else top_Pixel #翻转判定 if pixel_wanted(current_pixel) and not pixel_wanted(last_pixel): flag = True if flag and not pixel_wanted(current_pixel): flag = False if(flag): coordinate_List.append((x,y))
coordinate_List中的点如下图
然后就是将上面获得coordinate列表进行处理
将coordinate列表中每一列的最小坐标和最大坐标进行记录
因为每一列记录的数量并不确定(应该可以在上一步改进一下),所以需要遍历多次
首先找到第一个列出现的坐标,将它的行信息记录(行信息最小确定),
然后遍历出全部的同列的坐标,比较行坐标,如果大的就将最大的代替(行信息最大确定),用一个新的列表记录数据
coordinate_Min_Max_List = [] #找最小最大 for i in range(im.size[0]): min=-1 max=-1 for coordinate in coordinate_List: if coordinate[0] == i: min = coordinate[1] max = coordinate[1] break for coordinate in coordinate_List: if coordinate[0] == i: if coordinate[1]>max: max = coordinate[1] coordinate_Min_Max_List.append(min) coordinate_Min_Max_List.append(max)
其中要将min和max都初始化为一个坐标不存在的值比如-1,为了在下一步多圈且有空隙情况下,不会出现残影现象,如下图
上一步的最后得到一个列表,第n列的最小行和最大行分别是第2n和2n+1元素,结果中的-1,为了让下一步不会画进去
然后就是绘制图片了,每一列将列表中对应的最小行到最大行涂满
#上色 for x in range(im.size[0]): for y in range(im.size[1]): min = coordinate_Min_Max_List[x*2] max = coordinate_Min_Max_List[x*2+1] if min<y<max: im.putpixel((x,y),(0,255,0)) else: #可以把非红圈的上掩膜遮住 pass
至此,就是类似opencv的算法实现,虽然还差翻转做与操作,但是已经比opencv生成的效果好,写成函数后续调用,
然后就是简单的翻转90度,再调用一次这个函数再做一遍
def Cal_S(im): im_0 = im.rotate(0) im_90 = im.rotate(90, expand=True) im_0 = fillPoly(im_0) im_90 = fillPoly(im_90) im_90 = im_90.rotate(-90, expand=True) i=0 for x in range(im.size[0]): for y in range(im.size[1]): if(im_0.getpixel((x,y))==(0,255,0) and im_90.getpixel((x,y))==(0,255,0)): im.putpixel((x,y),(0,255,0)) i+=1 return i/(im.size[0]*im.size[1])
做两遍的效果图
可以看到效果非常不错,但是依旧有个别图像有问题,比如十字分布的,
但现在的话误差已经降低非常多了,这些极其个别的十字现象可以手动把原图切割一下,或者干脆不处理了
所有代码,画出绿图片为了方便直观的查看,函数中可以把图片顺便保存一下,总体看一下效果
from PIL import Image def pixel_wanted(pix): return pix==(237,28, 36) def fillPoly(im): coordinate_List = [] top_Pixel = (0,0,0) for x in range(im.size[0]): flag = False #初始化每一列翻转位为False for y in range(im.size[1]): current_pixel = im.getpixel((x,y)) last_pixel = im.getpixel((x,y-1)) if y>0 else top_Pixel #翻转判定 if pixel_wanted(current_pixel) and not pixel_wanted(last_pixel): flag = True if flag and not pixel_wanted(current_pixel): flag = False if(flag): coordinate_List.append((x,y)) coordinate_Min_Max_List = [] #找最小最大 for i in range(im.size[0]): min=-1 max=-1 for coordinate in coordinate_List: if coordinate[0] == i: min = coordinate[1] max = coordinate[1] break for coordinate in coordinate_List: if coordinate[0] == i: if coordinate[1]>max: max = coordinate[1] coordinate_Min_Max_List.append(min) coordinate_Min_Max_List.append(max) #上色 for x in range(im.size[0]): for y in range(im.size[1]): min = coordinate_Min_Max_List[x*2] max = coordinate_Min_Max_List[x*2+1] if min<y<max: im.putpixel((x,y),(0,255,0)) else: #可以把非红圈的上掩膜遮住 pass return im def Cal_S(im): im_0 = im.rotate(0) im_90 = im.rotate(90, expand=True) im_0 = fillPoly(im_0) im_90 = fillPoly(im_90) im_90 = im_90.rotate(-90, expand=True) i=0 for x in range(im.size[0]): for y in range(im.size[1]): if(im_0.getpixel((x,y))==(0,255,0) and im_90.getpixel((x,y))==(0,255,0)): im.putpixel((x,y),(0,255,0)) i+=1 return i/(im.size[0]*im.size[1])
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
更新日志
- 黄乙玲1988-无稳定的爱心肝乱糟糟[日本东芝1M版][WAV+CUE]
- 群星《我们的歌第六季 第3期》[320K/MP3][70.68MB]
- 群星《我们的歌第六季 第3期》[FLAC/分轨][369.48MB]
- 群星《燃!沙排少女 影视原声带》[320K/MP3][175.61MB]
- 乱斗海盗瞎6胜卡组推荐一览 深暗领域乱斗海盗瞎卡组分享
- 炉石传说乱斗6胜卡组分享一览 深暗领域乱斗6胜卡组代码推荐
- 炉石传说乱斗本周卡组合集 乱斗模式卡组最新推荐
- 佟妍.2015-七窍玲珑心【万马旦】【WAV+CUE】
- 叶振棠陈晓慧.1986-龙的心·俘虏你(2006复黑限量版)【永恒】【WAV+CUE】
- 陈慧琳.1998-爱我不爱(国)【福茂】【WAV+CUE】
- 咪咕快游豪礼放送,百元京东卡、海量欢乐豆就在咪咕咪粉节!
- 双11百吋大屏焕新“热”,海信AI画质电视成最大赢家
- 海信电视E8N Ultra:真正的百吋,不止是大!
- 曾庆瑜1990-曾庆瑜历年精选[派森][WAV+CUE]
- 叶玉卿1999-深情之选[飞图][WAV+CUE]