热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

pythonopencv椭圆拟合并求交点

一、用到的函数1.cv2.findContours()image,contours,hierarchycv2.findContours(image,mode,method[,c
一、用到的函数

1.cv2.findContours()

image,contours,hierarchy =
cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]])

输入:
image:输入图像;

mode:轮廓的检索模式
1.cv2.RETR_EXTERNAL表示只检测外轮廓
  2.cv2.RETR_LIST检测的轮廓不建立等级关系
 3.cv2.RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
 4.cv2.RETR_TREE建立一个等级树结构的轮廓。

method:为轮廓的近似办法
 1.cv2.CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1
 2.cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标

输出
image:与输入image类似的一张二值图;

contours:list结构,列表中每个元素代表一个边沿信息。每个元素是(x,1,2)的三维向量,x表示该条边沿里共有多少个像素点,第三维的那个“2”表示每个点的横、纵坐标;
注意:如果输入选择cv2.CHAIN_APPROX_SIMPLE,则contours中一个list元素所包含的x点之间应该用直线连接起来,这个可以用cv2.drawContours()函数观察一下效果。

hierarchy:返回类型是(x,4)的二维ndarray。x和contours里的x是一样的意思。如果输入选择cv2.RETR_TREE,则以树形结构组织输出,hierarchy的四列分别对应下一个轮廓编号、上一个轮廓编号、父轮廓编号、子轮廓编号,该值为负数表示没有对应项。

2.ellipse = cv2.fitEllipse(cnt)

输入
cnt即1中所获取的轮廓点集
输出
ellipse = [ (x, y) , (a, b), angle ]
其中(x,y)为中心点位置,a为长轴长度,b为短轴长度,angle为中心旋转角度

3. cv2.ellipse(image, centerCoordinates, axesLength, angle, startAngle, endAngle, color [, thickness[, lineType[, shift]]])

输入
image:它是要在其上绘制椭圆的图像。
centerCoordinates:它是椭圆的中心坐标。坐标表示为两个值的元组,即(X坐标值,Y坐标值)。
axesLength:它包含两个变量的元组,分别包含椭圆的长轴和短轴(长轴长度,短轴长度)。
angle:椭圆旋转角度,以度为单位。
startAngle:椭圆弧的起始角度,以度为单位。
endAngle:椭圆弧的终止角度,以度为单位。
color:它是要绘制的形状边界线的颜色。对于BGR,我们通过一个元组。例如:(255,0,0)为蓝色。
thickness:是形状边界线的粗细像素。厚度-1像素将用指定的颜色填充形状。
lineType:这是一个可选参数,它给出了椭圆边界的类型。
shift:这是一个可选参数。它表示中心坐标中的小数位数和轴的值。

二、代码实现

import cv2
import numpy as np
import PIL.Image as Image
import math
from skimage.draw import linedef FitEll(image_path):image_uf = cv2.imread(image_path)print("image的形状{}".format(image_uf.shape))binary = cv2.Canny(image_uf, 50, 150)cnt, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)image_f = np.zeros(image_uf.shape, dtype=np.uint8)step = 0for i in range(len(cnt)):ellipse = cv2.fitEllipse(cnt[i])# 绘制椭圆 cv2.fitEllipse(cnt) cnt为一组轮廓点,返回值ellipse = [(x, y) , (a, b), angle] a,b为长短轴,angle为中心旋转角度cv2.ellipse(image_f,ellipse,(255-step*40,255-step*40,255-step*40),-1)(x, y), (a, b), ang = ellipsestep = step+1cv2.imshow('out',image_f)cv2.waitKey(0)image_f = Image.fromarray(cv2.cvtColor(image_f,cv2.COLOR_BGR2RGB))res_image_f = image_f.convert('P')return res_image_fif __name__ == '__main__':image_path = "test/test.png"res_image_f = FitEll(image_path)res_image_f.save("test/test_result.png")

左侧为原图,右侧为椭圆拟合结果

三、加料内容

如上图所示的两个椭圆,求经过小椭圆右端点且与小椭圆长轴垂直的直线与大椭圆的第一个交点位置。
直接上代码

import cv2
import numpy as np
import PIL.Image as Image
import math
from skimage.draw import linedef FitEll(image_path):image_uf = cv2.imread(image_path)print("image的形状{}".format(image_uf.shape))binary = cv2.Canny(image_uf, 50, 150)cnt, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)image_f = np.zeros(image_uf.shape, dtype=np.uint8)step = 0cnt = sorted(cnt, key=lambda x: len(x))max_index = len(cnt)-1for i in range(len(cnt)):ellipse = cv2.fitEllipse(cnt[i])# 绘制椭圆 cv2.fitEllipse(cnt) cnt为一组轮廓点,返回值ellipse = [(x, y) , (a, b), angle] a,b为长短轴,angle为中心旋转角度cv2.ellipse(image_f,ellipse,(255-step*40,255-step*40,255-step*40),-1)(x, y), (a, b), ang = ellipseif i!=max_index:p_l_x = x - (b / 2 * math.sin(ang * (math.pi) / 180))p_l_y = y + (b / 2 * math.cos(ang * (math.pi) / 180))p_r_x = x + (b / 2 * math.sin(ang * (math.pi) / 180))p_r_y = y - (b / 2 * math.cos(ang * (math.pi) / 180))cv2.circle(image_f, (int(p_l_x),int(p_l_y)), 8, (255,0,0), -1)cv2.circle(image_f, (int(p_r_x),int(p_r_y)), 8, (255, 0, 0), -1)else:x_b, y_b, w_b, h_b = cv2.boundingRect(cnt[i])#cv2.rectangle(image_f, (x_b, y_b), (x_b + w_b, y_b + h_b), (255, 0, 0), 1)if p_r_y!=p_l_y:k_l = -(p_r_x-p_l_x)/(p_r_y-p_l_y)b_l = -k_l*p_r_x+p_r_ypa, pb = (x_b, int(k_l * x_b + b_l)), ((x_b + w_b), int(k_l * (x_b + w_b) + b_l))else:pa, pb = (int(p_r_x), y_b), (int(p_r_x), y_b + h_b)# 枚举2点之间的线段点for pt in zip(*line(*pa, *pb)):#dis = cv2.pointPolygonTest(cnt[i], pt, True)if cv2.pointPolygonTest(cnt[i], pt, False) == 0: # 若点在轮廓上cv2.circle(image_f, pt, 8, (0, 0, 255), -1)cv2.line(image_f,(int(p_r_x),int(p_r_y)),pt,(0,255,0),4)breakstep = step+1cv2.imshow('out',image_f)cv2.waitKey(0)image_f = Image.fromarray(cv2.cvtColor(image_f,cv2.COLOR_BGR2RGB))res_image_f = image_f.convert('P')return res_image_fif __name__ == '__main__':image_path = "test/test.png"res_image_f = FitEll(image_path)res_image_f.save("test/test_result.png")

在这里插入图片描述
这里主要用了一个cv2.pointPolygonTest(cnt[i], pt, False)函数,cnt即为最前面提取到的轮廓点集,pt为遍历线段上某一点坐标,返回值0(在轮廓上),1(在轮廓内),-1(在轮廓外),当返回值为0时,pt即为交点坐标。

求交点部分参考这位朋友的博客
(https://javis486.blog.csdn.net/article/details/109542852)


推荐阅读
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 本文介绍了游标的使用方法,并以一个水果供应商数据库为例进行了说明。首先创建了一个名为fruits的表,包含了水果的id、供应商id、名称和价格等字段。然后使用游标查询了水果的名称和价格,并将结果输出。最后对游标进行了关闭操作。通过本文可以了解到游标在数据库操作中的应用。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • 本文讨论了Kotlin中扩展函数的一些惯用用法以及其合理性。作者认为在某些情况下,定义扩展函数没有意义,但官方的编码约定支持这种方式。文章还介绍了在类之外定义扩展函数的具体用法,并讨论了避免使用扩展函数的边缘情况。作者提出了对于扩展函数的合理性的质疑,并给出了自己的反驳。最后,文章强调了在编写Kotlin代码时可以自由地使用扩展函数的重要性。 ... [详细]
  • 本文介绍了机器学习手册中关于日期和时区操作的重要性以及其在实际应用中的作用。文章以一个故事为背景,描述了学童们面对老先生的教导时的反应,以及上官如在这个过程中的表现。同时,文章也提到了顾慎为对上官如的恨意以及他们之间的矛盾源于早年的结局。最后,文章强调了日期和时区操作在机器学习中的重要性,并指出了其在实际应用中的作用和意义。 ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
  • 第四章高阶函数(参数传递、高阶函数、lambda表达式)(python进阶)的讲解和应用
    本文主要讲解了第四章高阶函数(参数传递、高阶函数、lambda表达式)的相关知识,包括函数参数传递机制和赋值机制、引用传递的概念和应用、默认参数的定义和使用等内容。同时介绍了高阶函数和lambda表达式的概念,并给出了一些实例代码进行演示。对于想要进一步提升python编程能力的读者来说,本文将是一个不错的学习资料。 ... [详细]
  • 基于dlib的人脸68特征点提取(眨眼张嘴检测)python版本
    文章目录引言开发环境和库流程设计张嘴和闭眼的检测引言(1)利用Dlib官方训练好的模型“shape_predictor_68_face_landmarks.dat”进行68个点标定 ... [详细]
  • 这篇文章主要介绍了Python拼接字符串的七种方式,包括使用%、format()、join()、f-string等方法。每种方法都有其特点和限制,通过本文的介绍可以帮助读者更好地理解和运用字符串拼接的技巧。 ... [详细]
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
  • EzPP 0.2发布,新增YAML布局渲染功能
    EzPP发布了0.2.1版本,新增了YAML布局渲染功能,可以将YAML文件渲染为图片,并且可以复用YAML作为模版,通过传递不同参数生成不同的图片。这个功能可以用于绘制Logo、封面或其他图片,让用户不需要安装或卸载Photoshop。文章还提供了一个入门例子,介绍了使用ezpp的基本渲染方法,以及如何使用canvas、text类元素、自定义字体等。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • WhenIusepythontoapplythepymysqlmoduletoaddafieldtoatableinthemysqldatabase,itdo ... [详细]
author-avatar
美好生活的日子
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有