整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

教你用OpenCV 和 Python实现圆物检测

教你用OpenCV 和 Python实现圆物检测

于python使用OpenCV实现在一张图片中检测出圆形,并且根据圆检测结果信息,绘制 标记出圆的边界和圆心。

1 HoughCircles 霍夫圆检测

在Opencv中使用HoughCircles函数实现圆的检测,具体函数参数如下:

  • image: 输入图像,8位灰度单通道图像
  • method: 检测圆的方法,目前OpenCV中有HOUGH_GRADIENTHOUGH_GRADIENT_ALT两种方法。
  • dp: 检测圆心的累加器图像的分辨率与输入图像之比的倒数,如果dp=1时,累加器和输入图像具有相同的分辨率。如果dp=2,累加器输入图像便有输入图像一半那么大的宽度和高度。减少图像的分辨率(宽高变小)是为了减少计算量,一般默认为1就好,保持原有图像精度。
  • minDist: 检测到的两个圆心之间的最小距离。如果参数太小,除了真实的一个圆圈之外,可能错误地检测到多个相邻的圆圈。如果太大,可能会遗漏一些圆圈。
  • circles: 检测到的圆的信息输出向量(x,y,r),分别代表检测到圆的中心坐标和圆半径。
  • param1: Canny 边缘检测的高阈值,低阈值被自动置为高阈值的一半,默认为 100。也就是说检测图像中像素点的值大于param1是会检测为边缘。
  • param2: 表示在检测阶段圆心的累加器阈值。它越小的话,会误检测到更多根本不存在的小圆,而越大,能通过检测的圆就更加接近完美的圆形了。
  • minRadius: 表示图像中能检测到最小圆的半径的值。
  • maxRadius: 表示图像中检测到的圆的最大半径的值。

参数设置总结

  • param2值的设置根据要检测图像中圆的大小进行设置,minRadius最小圆半径和maxRadius最大圆半径可以辅助我们更好选择圆,如果没有特殊需要就都默认为0。minDist可以帮助我们筛选掉检测相近的圆。
  • 霍夫圆检测的原理:第一步通过Canny边缘检测算法检测边缘,发现可能的圆心,然后再计算边缘像素点到圆心的距离估计圆的半径。


2 HoughCircles 霍夫圆检测代码实现

实现霍夫圆检测的实现代码非常简单,首先使用cv2.cvtColor函数将要检测的图像转换为灰度图像,然后调用cv2.HoughCircles霍夫圆检测函数进行检测,检测返回所有圆的中心坐标和半径信息向量circles(x,y,r)

注意: 霍夫圆检测对噪声比较敏感,所以进行霍夫圆检测的之前可以先进行中值滤波cv2.medianBlur

def circle_detect(image):
    # 灰度化
    gray=cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    # 输出图像大小,方便根据图像大小调节minRadius和maxRadius
    print(image.shape)
    # 进行中值滤波
    img=cv2.medianBlur(gray, 5)

    # 霍夫变换圆检测
    circles=cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 1, 50, param1=100, param2=30, minRadius=5, maxRadius=100)
    for circle in circles[0]:
        # 圆的基本信息
        print(circle[2])
        # 坐标行列-圆心坐标
        x=int(circle[0])
        y=int(circle[1])
        # 半径
        r=int(circle[2])
        # 在原图用指定颜色标记出圆的边界
        cv2.circle(image, (x, y), r, (0, 0, 255), 3)
        # 画出圆的圆心
        cv2.circle(image, (x, y),5, (0, 255, 0), -1)

    cv2.imshow("image",image)

img=cv2.imread(r'D:\yolov5-5.0\data\images\1.jpg')
circle_detect(image=img)

cv2.waitKey(0)

最后再借助OpenCV中的画圆函数cv2.circle,cv2.Circle函数参数

  • img: 要在其上绘制圆的输入图像
  • center: 绘制圆的中心坐标(x,y),未设置shift参数时,默认为整数int类型。
  • radius: 绘制圆的半径,未设置shift参数时,默认为整数int类型
  • color: 绘制圆的边界线的颜色,OpenCV读取图像后,图像格式为BGR,即【0,255,255】表示用红色绘制圆的边缘。
  • thickness:圆的边界线的粗细像素值。值为负(-1)时绘制实心圆。
  • lineType:可选参数,线的类型:虚线、实线
  • shift:可选参数,圆心坐标点和半径值的小数点位数。

3 检测效果

通过合理的控制minDistminRadiusmaxRadiusparam2这四个参数的值,最终的检测效果如下图:

参考资料:
https://www.cnblogs.com/april0315/p/13657682.html
https://www.cnblogs.com/bjxqmy/p/12333022.ht

后台回复:项目实战,即可获取代码下载使用。

往期精彩:教你用OpenCV 和 Python给证件照换底色(蓝底 <->红底->白底) &&教你用OpenCV和Python实现手掌检测和手掌计数

制圆形和圆弧都使用arc()方法:

Arc(x, y, r, startAngle, endAngle, antiClockwise)

Arc()方法是从(x,y)位置画出半径为r的圆形;

startAngle及endAngle决定圆弧的起点角度与终点角度; startAngle: 起点是X轴方向, 即3点钟方向。

antiClockwise参数决定是否已逆时针方向绘图,逆时针为true,顺时针为false。


在canvas中所有涉及角度的坐标系有两点注意的:

0弧度的方向是正右方向。

弧度的顺时针和逆时针:


角度与弧度转公式

角度转弧度 π/180×角度

弧度变角度 180/π×弧度


将角度转换为弧度,计算公式可以参考下面的公式:

radians=degrees * Math.PI/180

degrees 角度

radians 弧度

圆的弧度(360):360 * Math.PI/180=Math.PI * 2=6.28

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>绘制圆</title>
<script type="text/javascript">
function drawCircle(){
var canvas=document.getElementById('myCanvas');
var ctx=canvas.getContext('2d');
//开始绘图--圆
ctx.strokeStyle="#336600"; //设定边框颜色
ctx.lineWidth=10; //设定线条宽度 10px
ctx.fillStyle="#FF0000"; //设定填充颜色
ctx.beginPath(); //路径开始
ctx.arc(100,100,50,0,Math.PI*2,true); //起始点(100,100)半径50的圆
ctx.closePath(); //关闭路径
ctx.fill(); //绘出填满图形
ctx.stroke(); //绘出边框
}
</script>
<!--style标记内是CSS语法-->
<style type="text/css">
Canvas { border: 1px solid black; } //将框线设为1px
</style>
</head>
<body>
<input type="button" value=" 画 圆 " onclick="drawCircle();"><br />
<canvas id="myCanvas" width="400" height="200"></canvas>
</body>
</html>

绘制圆弧

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>绘制圆弧</title>
<style type="text/css">
canvas{
border: 1px solid #000;
}
</style>
</head>
<body>
<canvas width="600" height="400"></canvas>
</body>
<script type="text/javascript">
var canvas=document.querySelector("canvas")
var ctx=canvas.getContext("2d");
ctx.beginPath(); //开始绘制路径
// ctx.arc(100, 100, 60, 0, 6.28, false);
// ctx.arc(100, 100, 60, 0, -6.28, true);
ctx.arc(100, 100, 60, 0, Math.PI * 2, false);
ctx.stroke(); //显示路径线
ctx.fillStyle="pink";   //设置填充颜色
ctx.fill(); //填充颜色
</script>
</html>


绘制笑脸


在前端开发中经常会用到很多的简易图形,例如三角形,箭头,圆形等。有很多人一开始会想着用小的图片实现,不过这样会增加页面请求次数,延缓页面加载效果。

在CSS中有个border属性,它完全可以达到制作各种简易图形的效果,今天我们就一起来看看吧。

文章中的代码都已经放在了github上,感兴趣的同学自取。

https://github.com/zhouxiongking/article-pages/blob/master/articles/border/border.html

CSS

border讲解

在制作各种简易图形之前,我们先来看看border属性的使用。

border是一个复合属性。

  • border-width表示边框宽度。

  • border-style表示边框样式,设置实线,虚线,点状等。

  • border-color表示边框颜色,还可以设置transparent,表示透明。

border又分为上下左右四个方向,每个方向都占据各自的空间,不会出现重叠的地方,尤其是在四个方向的边框都设置的情况下,在四个角处也不会出现重叠。

我们来看个最简单的例子,在四个方向上都设置边框,赋予不同的颜色。

图片1

通过上面的图片1可以看出,四个角处是分离,没有重合的。

梯形

首先我们来看看梯形的效果图。

梯形效果图

我们再来分析下梯形是如何实现的。

  • 因为我们完全是通过border设置,所以这个div的高度应该为0。

  • 梯形的左右两个腰,恰好如同border在角的衔接处,然后将两侧的border-style设置为transparent。

因此我们可以得到以下的CSS代码。

梯形的CSS代码

修改border-left和border-right的宽度值,可以改变梯形的形状。

三角形

三角形也分为上下左右四个方向,我们首先来看看总体的形状。

三角形

然后我们也来分析下如何实现这个效果,以下三角形为例。

  • 因为是呈现三角形的形状,刚好契合border在角落的衔接处,因此高度和宽度都应该为0。

  • 下三角形是上部有区域,所以要设置border-top。

  • border-left和border-right两个方向都要设置宽度,然后设置为透明即可。

因此得到以下的CSS代码,设置不同方向border的宽度,三角形的形状也会跟着变。

下三角形CSS代码

同理,只要掌握了其中一个方向的三角形原理,就会轻松写出其他方向三角形的CSS代码。

这里直接给出上三角形的CSS代码。

上三角形CSS代码

左三角形的CSS代码如下所示。

左三角形CSS代码

右三角形的CSS代码如下所示。

右三角形CSS代码

正方形-四种颜色

接下来我们看一种基本的只用border设计的形状。

图形

它的实现方式也很简单,只需要将width和height设置为0,然后将border四个方向的宽度设置成一样的即可。

得到的代码如下所示。

CSS代码

直角三角形

基于上述的实现,我们可以得到左下,左上,右上,右下四种三角形。

首先看看基本形状。

直角三角形

看到图形后,我们很容易发现,只要隐藏掉连接的两个方向的border,显示出另外两个方向的border,就可以得到直角三角形。

这里我们只展示出左上三角形的CSS代码。

左上直角三角形CSS代码

其他方向的直角三角形代码可类比得出,大家可以试一下。

六角星

首先我们看看六角星的形状。

六角星

看到这个图形,大家应该能想到可以由上下两个三角形构成,只要将上下两个三角形位置对应准确。

这里为了节省页面元素的空间,我们可以采用伪元素去实现。

  • 将页面显示元素设置为上三角形。

  • 利用:after伪元素设置下三角形。

  • 设置伪元素的position为absolute,调节right和top值。

通过上述分析,我们得到以下CSS代码。

六角星CSS代码

圆形

与border属性搭配使用的还有一个很常用的属性,那就是border-radius。

border-radius是专门设置圆角的,可以让90度角变为圆角。

我们首先看看最基本的圆形的样子。

圆形

其实我们只需要将border-radius属性设置为宽或者高的一半以上即可。代码如下所示。

圆形

同心圆

我们来看看同心圆的样子。

同心圆

同心圆只需要设置一个border边框,给border设置一个特殊的背景色,给div设置成白色背景即可。

同心圆CSS代码

半圆

我们来看看半圆的形状。

半圆

半圆的效果是如何实现的呢?

  • 首先元素自身高度设置为0,设定宽度值。

  • 设定上部和右部的border。

  • 设定左上角和右上角的border-radius值。

得到的代码如下所示。

上半圆

同理,下半圆,左半圆和右半圆修改对应的值就可以获得。

结束语

今天这篇文章主要通过border属性,画出了一系列简易的图形,这在实际中是很实用的,大家学会了吗?