python计算不规则图形面积算法
介绍:大三上做一个医学影像识别的项目,医生在原图上用红笔标记病灶点,通过记录红色的坐标位置可以得到病灶点的外接矩形,但是后续会涉及到红圈内的面积在外接矩形下的占比问题,有些外接矩形内有多个红色标记,在使用网上的opencv的fillPoly填充效果非常不理想,还有类似python计算任意多边形方法也不理想的情况下,自己探索出的一种效果还不错的计算多圈及不规则图形的面积的算法。
医生提供的病灶标记图和原图,大部分长这样


但也有一些多圈情况


很明显,这些图片都是非常需要计算面积占比的,对样本需要筛选
通过百度,用opencv的填充来计算面积,一部分效果很差,单圈画不全,多圈都是错(用将面积计算结果上色,方便观察)



通过此算法之后,无论单圈,多圈,面积计算准确度提高许多




能较为准确的计算出不规则图形的面积
正文:算法的思想很简单,遍历图片每一列,通过色差判断是否遇到标记圈,将坐标全部记录,对每一列的坐标都进行最小行和最大行记录,确定每一列的最小和最大的坐标,然后上色(类似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])
python计算不规则图形面积算法的更多相关文章
- 机器学习实战笔记(Python实现)-01-K近邻算法(KNN)
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
- python 计算校验和
校验和是经常使用的,这里简单的列了一个针对按字节计算累加和的代码片段.其实,这种累加和的计算,将字节翻译为无符号整数和带符号整数,结果是一样的. 使用python计算校验和时记住做截断就可以了. 这里 ...
- 用Python实现随机森林算法,深度学习
用Python实现随机森林算法,深度学习 拥有高方差使得决策树(secision tress)在处理特定训练数据集时其结果显得相对脆弱.bagging(bootstrap aggregating 的缩 ...
- Python实现 K_Means聚类算法
使用 Python实现 K_Means聚类算法: 问题定义 聚类问题是数据挖掘的基本问题,它的本质是将n个数据对象划分为 k个聚类,以便使得所获得的聚类满足以下条件: 同一聚类中的数据对象相似度较高 ...
- 如何用Python实现常见机器学习算法-1
最近在GitHub上学习了有关python实现常见机器学习算法 目录 一.线性回归 1.代价函数 2.梯度下降算法 3.均值归一化 4.最终运行结果 5.使用scikit-learn库中的线性模型实现 ...
- 使用python模拟实现KNN算法
一.KNN简介 1.KNN算法也称为K邻近算法,是数据挖掘分类技术之一.所谓K最近邻,就是k个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代表. 2.KNN算法的核心思想是如果一个样本 ...
- python 的常见排序算法实现
python 的常见排序算法实现 参考以下链接:https://www.cnblogs.com/shiluoliming/p/6740585.html 算法(Algorithm)是指解题方案的准确而完 ...
- [转载] python 计算字符串长度
本文转载自: http://www.sharejs.com/codes/python/4843 python 计算字符串长度,一个中文算两个字符,先转换成utf8,然后通过计算utf8的长度和len函 ...
- Python实现各种排序算法的代码示例总结
Python实现各种排序算法的代码示例总结 作者:Donald Knuth 字体:[增加 减小] 类型:转载 时间:2015-12-11我要评论 这篇文章主要介绍了Python实现各种排序算法的代码示 ...
随机推荐
- docker下安装Redis
Docker介绍 1.节约时间.快速部署和启动 2.节约成本 3.标准化应用发布 4.方便做持续继承 5作为集群中的轻量主机或节点 6.方便构建基于SOA或者微服务架构的系统 Docker中文文档 h ...
- ES6入门系列 ----- 使用Proxy 实现观察者模式
观察者模式是指函数自动观察数据对象的变化, 一旦对象有变化,函数就会自动执行. 它定义了一种一对多的依赖关系,我们用Proxy来实现一个简单的观察者模式(PS: 初学我们认为 观察者模式 == 发布订 ...
- STM32 掉电检测程序
当VDD下降到PVD阀值以下或当VDD上升到PVD阀值之上时,根据外部中断第16线的上升/下降边沿触发设置,就会产生PVD中断 void PVD_IRQHandler(void) { led_ctrl ...
- Fundebug微信小程序BUG监控服务支持Source Map
摘要: 自动还原真实出错位置,快速修复BUG. Source Map功能 微信小程序的Source Map功能目前只在 iOS 6.7.2 及以上版本支持. 微信小程序在打包时,会将所有 js 代码打 ...
- MySQL数据篇(五)--SQL对数据进行按月统计,或对数据进行按星期统计
对于所有的需求,当你不知道怎么处理的时候,你就先用最简单的方法,或者说的明白一点,用最原始的方法,先实现业务需求再说. 一.对提现队列数据表“ims_checkout_task”进行汇总统计,按月汇总 ...
- java.lang.IllegalArgumentException: Prometheus requires that all meters with the same name have the same set of tag keys.
创建Spring Cloud Sleuth对应Zipkin服务,引入依赖: <dependency> <groupId>io.zipkin.java</groupId&g ...
- Hive性能调优(二)----数据倾斜
Hive在分布式运行的时候最害怕的是数据倾斜,这是由于分布式系统的特性决定的,因为分布式系统之所以很快是由于作业平均分配给了不同的节点,不同节点同心协力,从而达到更快处理完作业的目的. Hive中数据 ...
- python pip 升级 或者换源
1. 临时换源python -m pip install --upgrade pip -i https://pypi.douban.com/simple pip国内的一些镜像 阿里云 https ...
- Python 修饰符@用法
def funA(desA): print("It's funA") def funB(desB): print(desB( )) print("It's funB&qu ...
- 九、Swift对象存储服务(双节点搭建)
九.Swift对象存储服务(双节点搭建) 要求:Controoler节点需要2块空盘 Compute节点需要再加2块空盘 本次搭建采用Controller 和 Compute双节点节点做swift组件 ...