jQuery火箭图标返回顶部代码

jQuery火箭图标返回顶部代码

滚动滑动条后,查看右下角查看效果。很炫哦!!

适用浏览器:IE8、360、FireFox、Chrome、Safari、Opera、傲游、搜狗、世界之窗.

opencv-python图像轮廓

本章节介绍图像轮廓查找和绘制,图像轮廓的多边形逼近,凸包和外接矩形等。

图像轮廓是具有相同颜色或灰度的连续点的曲线,轮廓在形状分析和物体的检测和识别中很有用。

为了检测的准确性,需要先对图形进行二值化或canny操作。

提取轮廓时会修改原图像,如果要继续使用原图像,应该先把原图像存入其他变量中。

1 查找并绘制轮廓

opencv中查找轮廓的函数

findContours(image, mode, method[, contours[, hierarchy[, offset]]]) -> image, contours, hierarchy

参数说明:

mode 查找轮廓的模式:

RETR_EXTERNAL=0,只检测外围轮廓;

RETR_LIST=1,检测的轮廓不建立等级关系,检测所有轮廓(常用);

RETR_CCOMP=2,每层最多两级,从小到大,从里到外;

RETR_TREE=3,按照树型存储轮廓,层级从右到左,从外到内。

 method 轮廓近似方法也叫 ApproximationMode:

CHAIN_APPROX_NONE,保留轮廓上的所有点;
CHAIN_APPROX_SIMPLE,只保留边角的点,存储信息较少,比较常用。

返回值:返回img, contours和hierarchy(图像,轮廓和层级),返回的轮廓是最常用的,contours是list类型,表示所有轮廓,由不同层级的ndarray轮廓组成,每个轮廓保存其轮廓的坐标点。

opencv中绘制轮廓的函数:

drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]]) -> image

img:要绘制的轮廓图像;

contours:轮廓点;

contourldx:要绘制的轮廓编号,1表示绘制所有轮廓;
color:绘制轮廓颜色;

thickness:线宽,-1表示全部填充。

查找并绘制下图的轮廓:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import cv2
import numpy as np
 
img = cv2.imread('./contours.png')
 
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
 
#binary_img = cv2.adaptiveThreshold(gray_img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,3,0) #自适应阈值二值化
thresh,binary_img = cv2.threshold(gray_img,130,255,type=cv2.THRESH_TOZERO)
 
image,contours,hierarchy = cv2.findContours(binary_img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
 
img_copy = img.copy() 
cv2.drawContours(img_copy,contours,-1,[0,0,255],1#绘制轮廓,绘制轮廓会改变输入的图像,最好备份一份原图。
 
#print(len(contours))
 
cv2.imshow('img',img)
#cv2.imshow('binary_img',binary_img)
cv2.imshow('img_copy',img_copy)
 
cv2.waitKey(0)
cv2.destroyAllWindows()

如果把thickness线宽,改为-1会进行填充。

多边形填充:

如果想要对上面的某些多边形进行填充,可以用 fillPoly(img,pts,color) pts 表示多边形数组,其中每个多边形均表示为顶点数组。单个多边形填充可以用 fillConvexPoly(img,points,color)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import cv2
import numpy as np
 
img = cv2.imread('./contours.png')
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
 
thresh,binary_img = cv2.threshold(gray_img,127,255,cv2.THRESH_BINARY)  #图像二值化
 
image,contours,hierarchy = cv2.findContours(binary_img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) #检测轮廓
 
# poly = np.array([[300,50],[50,250],[300,300]])  #定义多边形的顶点
 
img_copy = img.copy()  #多边形填充也会改变原图,需要原图的话可以拷贝一下再填充
fill_img = cv2.fillPoly(img_copy,[contours[1],contours[3],contours[10]],(0,0,255))  #多边形填充,可以直接用检测轮廓返回的轮廓坐标点来填充,也可以自定义顶点
 
#fill_img = cv2.fillPoly(img,[contours[1],poly],(0,0,255))
 
cv2.imshow('img',img)
cv2.imshow('fill_img',fill_img)
 
 
cv2.waitKey(0)
cv2.destroyAllWindows()

 计算轮廓的面积和周长:

计算面积:contourArea(contour[, oriented]) -> retval   contour表是需要计算轮廓

计算周长:arcLength(curve, closed) -> retval   curve表示需要计算的轮廓,closed表示是否闭合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import cv2
import numpy as np
 
img = cv2.imread('./contours.png')
 
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
 
#binary_img = cv2.adaptiveThreshold(gray_img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,3,0) #自适应阈值二值化
thresh,binary_img = cv2.threshold(gray_img,130,255,type=cv2.THRESH_TOZERO)
 
 
image,contours,hierarchy = cv2.findContours(binary_img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
 
img_copy = img.copy() 
cv2.drawContours(img_copy,contours,0,[0,0,255],-1#绘制轮廓,绘制轮廓会改变输入的图像,最好备份一份原图。
 
#print(len(contours))
 
#轮廓面积:指每个轮廓中所有的像素点围成区域的面积,单位是像素。可以用来分析每个轮廓的隐含信息,比如通过轮廓面积区分物体大小来识别物体。
# 在查找到轮廓后,可能会有很多细小轮廓,可以通过面积来过滤。contourArea(contour)   arcLength(curve,closed)  =(轮廓,是否闭合)
area = cv2.contourArea(contours[0])   #计算某个轮廓的面积,contours轮廓是list类型
length = cv2.arcLength(contours[0],closed=True#计算某个轮廓的周长
 
print('area:',area,'length:',length)
 
cv2.imshow('img',img)
#cv2.imshow('binary_img',binary_img)
cv2.imshow('img_copy',img_copy)
 
cv2.waitKey(0)
cv2.destroyAllWindows()

 

也可以绘制比较复杂的图形的轮廓,比如绘制手的轮廓:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import cv2   #绘制轮廓
import numpy as np
 
img = cv2.imread('./hand.jpg')
 
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
 
#binary_img = cv2.adaptiveThreshold(gray_img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,5,0) #自适应阈值二值化 这种方式二值化后噪点多
 
thresh,binary_img = cv2.threshold(gray_img,40,255,type=cv2.THRESH_BINARY)
 
image,contours,hierarchy = cv2.findContours(binary_img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
print(len(contours))
 
img_copy = img.copy()
cv2.drawContours(img_copy,contours,-1,[0,0,255],2#绘制轮廓,绘制轮廓会改变输入的图像,最好备份一份原图。
 
cv2.imshow('img',img)
cv2.imshow('binary_img',binary_img)
cv2.imshow('img_copy',img_copy)
 
cv2.waitKey(0)
cv2.destroyAllWindows()

 2 图像轮廓的多边形逼近

findContours后轮廓的信息可能比较复杂不平滑,可以用approxPolyDP对轮廓用多边形来近似拟合,即多边形逼近(采用的Douglas-Peucker方法)。

DP原理:在轮廓曲线上面,不断找多边形最远的点加入形成新的多边形,直到最短距离小于指定的精度。

opencv中的函数:

approxPolyDP(curve, epsilon, closed[, approxCurve]) -> approxCurve

curve 表示需要近似逼近的轮廓;

epsilon 表示DP算法使用的阈值,可以根据阈值的调整控制多边形逼近的形状。

closed 表示轮廓是否闭合。

返回值是个ndarray,表示轮廓近似逼近后的点的坐标,这些坐标点可以直接用drawContours来绘制,也可以用 polylines 绘制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import cv2   #绘制轮廓
import numpy as np
 
img = cv2.imread('./hand.jpg')
 
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
 
thresh,binary_img = cv2.threshold(gray_img,40,255,type=cv2.THRESH_BINARY)
 
image,contours,hierarchy = cv2.findContours(binary_img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
print(len(contours))
 
img_copy = img.copy()
cv2.drawContours(img_copy,contours,-1,[0,0,255],2#绘制轮廓,绘制轮廓会改变输入的图像,最好备份一份原图。
 
img_copy2 = img.copy()
approx = cv2.approxPolyDP(contours[0],20,closed=True#多边形逼近,返回值是个ndarray
cv2.drawContours(img_copy2,[approx],-1,[0,255,0],2#绘制多边形轮廓,轮廓类型要是list才行
 
#cv2.polylines(img_copy,[approx],True,[0,255,0],2)  #也可以直接用polylines绘制
 
cv2.imshow('img',img)
cv2.imshow('binary_img',binary_img)
cv2.imshow('img_copy',img_copy)
cv2.imshow('img_copy2',img_copy2)
 
cv2.waitKey(0)
cv2.destroyAllWindows()

3 凸包

凸包指的是完全包含原有轮廓,并且仅由轮廓上的点构成的多边形。凸包的每一处都是凸的,即在凸包内连接任意两点的直线都在凸包内。

opencv中凸包的函数

convexHull(points[, hull[, clockwise[, returnPoints]]]) -> hull

points 可以直接用轮廓

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import cv2   #绘制轮廓
import numpy as np
 
img = cv2.imread('./hand.jpg')
 
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
 
thresh,binary_img = cv2.threshold(gray_img,40,255,type=cv2.THRESH_BINARY)
 
image,contours,hierarchy = cv2.findContours(binary_img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
 
img_copy = img.copy()
cv2.drawContours(img_copy,contours,-1,[0,0,255],2#绘制轮廓,绘制轮廓会改变输入的图像,最好备份一份原图。
 
hull = cv2.convexHull(contours[0])  #凸包
#cv2.drawContours(img_copy,[hull],-1,[0,225,0],2) #绘制凸包
cv2.polylines(img_copy,[hull],True,[0,255,0],2#也可以直接用polylines绘制
 
cv2.imshow('img',img)
cv2.imshow('binary_img',binary_img)
cv2.imshow('img_copy',img_copy)
 
cv2.waitKey(0)
cv2.destroyAllWindows()

4 最大外接矩形和最小外接矩形

1)最大外接矩形

opencv中图形的最大外接矩形的函数

boundingRect(points) -> retval

points表示图形的轮廓

返回值是矩形的左上角坐标和矩形长宽

除了在原图上面绘制轮廓和外接矩形,也可以单独创建窗口绘制。

如下是绘制星星的最大外接矩形:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import cv2   #图像的最大外接矩形  boundingRect(contours)  参数是轮廓坐标点,返回矩形的左上角坐标和长宽
import numpy as np
 
img = cv2.imread('./contours.png')
 
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
 
thresh,binary_img = cv2.threshold(gray_img,40,255,type=cv2.THRESH_BINARY)
 
image,contours,hierarchy = cv2.findContours(binary_img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
 
contours_img = np.zeros(img.shape[:],np.uint8)  #创建白底图像画布绘制需要的轮廓
contours_img[:] = 255
 
img_copy = img.copy()
cv2.drawContours(contours_img,contours,10,[0,0,255],2#绘制轮廓,只单独绘制第二层轮廓
 
rect = cv2.boundingRect(contours[10])   # 矩形边框,返回值是矩形的左上角坐标和矩形长宽
x,y,w,h = rect
print('rect:',rect)
 
img_copy2 = cv2.rectangle(contours_img,(x,y),(x+w, y+h),(0,255,0),3#绘制矩形,注意绘制坐标为左上角和右下角坐标。
 
cv2.imshow('img',img)
cv2.imshow('img_copy',img_copy)
cv2.imshow('contours_img',contours_img)
 
cv2.waitKey(0)
cv2.destroyAllWindows()

2)最小外接矩形

opencv中最小外接矩形的函数是

minAreaRect(points) -> retval

返回最小外接矩形,是一个旋转的矩形,返回矩形的起始坐标(x,y),矩形的长宽,矩形旋转角度。

可以用 boxPoints(min_rect) 函数把旋转矩形的四个顶点坐标计算出来(注意坐标点应该是整型才行,这里返回的是float型)。

绘制五角星的最小外接矩形:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import cv2
import numpy as np
 
img = cv2.imread('./contours.png')
 
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
 
thresh,binary_img = cv2.threshold(gray_img,127,255,cv2.THRESH_BINARY) #二值化
 
image,contours,hierarchy = cv2.findContours(binary_img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)   #检测轮廓
 
img_copy = img.copy()
cv2.drawContours(img_copy,contours,10,[0,0,255],2#绘制轮廓
 
min_rect = cv2.minAreaRect(contours[10])  #返回最小外接矩形,是一个旋转的矩形,返回矩形的起始坐标(x,y),矩形的长宽,矩形旋转角度
print('min_rect',min_rect)
 
points = cv2.boxPoints(min_rect)  #这个函数可以把旋转矩形的四个顶点坐标计算出来(注意坐标点应该是整型才行,这里返回的是float型)
print('point:\n',points)
 
rect_points = np.round(points).astype('int64'#把坐标点类型转换为整数,如果直接int转的话会直接扔掉小数点后的数值,round可以四舍五入,再用astype转整数
print('rect_points:\n',rect_points)
 
cv2.drawContours(img_copy,[rect_points],0,[0,255,0],2)   #根据坐标点绘制最小外接矩形
 
cv2.imshow('img',img)
cv2.imshow('img_copy',img_copy)
 
cv2.waitKey(0)
cv2.destroyAllWindows()

5 最小外接圆和椭圆

1)最小外接圆

opencv中最小外接圆函数是

minEnclosingCircle(points) -> center, radius

返回最小外接圆的圆心,半径 == ((x,y),radius)

然后可以根据返回的圆心和半径用 circle 把圆绘制出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import cv2
import numpy as np
 
img = cv2.imread('./contours.png')
 
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
 
thresh,binary_img = cv2.threshold(gray_img,127,255,cv2.THRESH_BINARY) #二值化
 
image,contours,hierarchy = cv2.findContours(binary_img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)   #检测轮廓
 
img_copy = img.copy()
cv2.drawContours(img_copy,contours,10,[0,0,255],2#绘制轮廓
 
(x,y),radius = cv2.minEnclosingCircle(contours[10])  #返回最小外接圆,返回圆心,半径 == ((x,y),radius)
print((x,y),radius)
 
cir_center = (int(x),int(y))   #把圆心半径转换为整数
cir_radius = np.round(radius).astype('int64')
 
cv2.circle(img_copy,cir_center,cir_radius,[0,255,0],2)
 
cv2.imshow('img',img)
cv2.imshow('img_copy',img_copy)
 
cv2.waitKey(0)
cv2.destroyAllWindows()

2)椭圆拟合

opencv中轮廓椭圆拟合的函数

fitEllipse(points) -> retval

 返回椭圆的圆心,长短半轴,旋转角度参数,根据返回的参数直接用ellipse绘制椭圆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import cv2
import numpy as np
 
img = cv2.imread('./contours2.png')
 
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
 
thresh,binary_img = cv2.threshold(gray_img,127,255,cv2.THRESH_BINARY) #二值化
 
image,contours,hierarchy = cv2.findContours(binary_img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)   #检测轮廓
 
img_copy = img.copy()
cv2.drawContours(img_copy,contours,1,[0,0,255],2#绘制轮廓
 
ellipse = cv2.fitEllipse(contours[1])  #椭圆拟合
print('ellipse',ellipse)
 
cv2.ellipse(img_copy,ellipse,[0,255,0])  #绘制椭圆
 
cv2.imshow('img',img)
cv2.imshow('img_copy',img_copy)
 
cv2.waitKey(0)
cv2.destroyAllWindows()

 

posted @   寒水浮云  阅读(417)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示