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实现各种排序算法的代码示 ...
随机推荐
- SpringBoot(七) SpringBoot整合Log4j
第一种打印debug日志方式: logging.level.com.demo.mapper: debug 第二种打印debug日志方式: 在resource文件夹下新建:logback.xml < ...
- Zipkin客户端链路追踪源码解析
我们知道,Zipkin这个工具可以帮助我们收集分布式系统中各个系统之间的调用连关系,而且除了Servlet之外还能收集:MQ.线程池.WebSocket.Feign.Hystrix.RxJava.We ...
- Redis哨兵模式大key优化
目前,Redis哨兵模式,内存资源有限,有很多key大于500M,性能待优化.需要迁移至Redis-cluster集群中. 涉及到的key如下: 0,hash,duser_record, ...
- katalon studio升级到6.3.3版本后如何生成测试报告
背景: katalon studio 6.3.0版本开始,默认不会生成测试报告,因此,原先自动化运行结果的邮件也就不会包含测试报告附件. 解决方法如下: 通过插件[basic reports]生成测试 ...
- 重启电脑 wamp图标是橙色(未变绿)
记录一个错误: 修复系统漏洞后,重启电脑,wamp没有开机自启动,手动启动后发现,图标是大红色变成了橙色,也就是服务未完全启动(1/2)状态. ??? 但是我其实也不知道是哪个服务(Apache/My ...
- 源码包安装转换rpm包
目录 纯净版虚拟机 1. 先安装个虚拟机,登陆nginx官网 http://nginx.org/选择一个稳定的版本 2. 右键复制地址,到新克隆的纯净虚拟机wget 下载 3.源码包 4.解压 tar ...
- mysql查询两张表更改一张表数据
(user 为要更改数据的表 ,set后边需要更改的内容, where后加条件) update user a,user_copy b set a.manager_introduct=b.rwjs wh ...
- 大话IdentityServer4之使用 IdentityServer4 保护 ASP.NET Core 应用
这几天一直在研究IdentityServer4在asp.net core3.0中的应用,下面说说我的理解: 我们每一个.net core 项目大家可以理解为我新建了一个动物园或者植物园等,注册用户想要 ...
- 4. static修饰符
一.static修饰符概述 1. static修饰的成员表明它属于这个类本身,而不属于该类的单个实例 把static修饰的成员变量和方法称为类变量.类方法 2. 不使用static修饰的成员则属于该类 ...
- 在python的虚拟环境venv中使用gunicorn
昨天遇到的问题,一个服务器上有好几个虚拟机环境. 我active进一个虚拟环境,安装了新的三方库之后, 使用gunicorn启动django服务, 但还是死活提示没有安装这个三方库. 一开始没有找到原 ...