基于opencv的车牌号码识别 必备基础知识

1、cv2.split 拆分通道

#拆分通道
import cv2

img = cv2.imread('D:/z/car.png')            #opencv读取图像文件
b, g ,r =cv2.split(img)                 #顺序是b,g,r,不是r,g,b
merged = cv2.merge([b,g,r])

cv2.imshow('image',img)
cv2.imshow("Blue 1", b)
cv2.imshow("Green 1", g)
cv2.imshow("Red 1", r)
cv2.imshow("merged 1", merged)
cv2.waitKey(0)   

运行结果如下:
请添加图片描述

2、cv2.merge 通道合并

import cv2
import numpy as np

img = cv2.imread('D:/z/car.png')
b, g ,r =cv2.split(img)

zeros = np.zeros(img.shape[:2], dtype = "uint8")          
merged_r = cv2.merge([zeros,zeros,r])      #通道分量为零可以理解为零矩阵

cv2.imshow('image',img)
cv2.imshow("Red 1", r)
cv2.imshow("merged_r",merged_r)
cv2.waitKey(0)

结果如下:
请添加图片描述

Note:

zeros = np.zeros(img.shape[:2], dtype = "uint8") 


在用numpy 去创建一个矩阵并想用它生成图片时一定要记住,矩阵中每个元素的类型必须是 dtype=np.uint8 也可以这样写 dtype = “uint8”

[0:2]是切片的意思,.shape 应当是OpenCV模块中处理图片的,是图片的一个属性,这个属性是个列表 ,然后对这个列表切片操作。

img.shape[ : 2] 表示取彩色图片的长、宽。
img.shape[ : 3] 则表示取彩色图片的长、宽、通道。

关于img.shape[0]、[1]、[2]
img.shape[0]:图像的垂直尺寸(高度)
img.shape[1]:图像的水平尺寸(宽度)
img.shape[2]:图像的通道数
在矩阵中,[0]就表示行数,[1]则表示列数。

3、cv2.imshow() 和 plt.show()

在用plt.imshow和cv2.imshow显示同一幅图时可能会出现颜色差别很大的现象。
这是因为:opencv的接口使用BGR,而matplotlib.pyplot 则是RGB模式

示例 1:

import cv2 
import numpy as np 
import matplotlib.pyplot as plt 
  
img = cv2.imread('D:/z/love.jpg')   #opencv接口  BGR !!!!!!
b,g,r = cv2.split(img) 
img2 = cv2.merge([r,g,b])           #plt接口     RGB !!!!!
plt.subplot(121);plt.imshow(img) 
plt.subplot(122);plt.imshow(img2) 
plt.show() 

运行结果如下图所示:
请添加图片描述

示例 2:

import cv2
import matplotlib.pyplot as plt

img = cv2.imread('D:/z/car.png')
b,g,r = cv2.split(img) 
image= cv2.merge([r,g,b])
image_merged = cv2.merge([r,g,b])

plt.figure(figsize=(10,6)) 
plt.subplot(2,3,1), plt.title('image')               #原图 
plt.imshow(image), plt.axis('on')
plt.subplot(2,3,2), plt.title('image_gray')          #灰度图片
plt.imshow(img,cmap='gray'), plt.axis('off')
plt.subplot(2,3,3), plt.title('image_merged')        
plt.imshow(image_merged), plt.axis('off')
plt.subplot(2,3,4), plt.title('r')                   
plt.imshow(r,cmap='gray'), plt.axis('off')           # r通道
plt.subplot(2,3,5), plt.title('g') 
plt.imshow(g,cmap='gray'), plt.axis('off')           # g通道
plt.subplot(2,3,6), plt.title('b')
plt.imshow(b,cmap='gray'), plt.axis('off')           # b通道
plt.show()

结果如下:
请添加图片描述

plt.imshow(img,cmap='gray')

转换为灰度

plt.subplot(2,3,1)

一个窗口显示多幅图像,要用到subplot
使用 plt.subplot 来创建小图。
eg:plt.subplot (2,3,1) 表示将整个图像窗口分为2行3列,当前位置为1

plt.axis('off')

关闭坐标区

4、卷积及相关操作


在数字图像处理领域,它早已广泛应用于邻域处理,但当时被称为“滤波器”。
卷积是一种广泛使用的数学运算,它在处理图像时为每个像素计算该像素的值与其相邻像素的值的加权和。其实很容易理解,就是内积运算。


用模板(掩膜/卷积核/滤波器)来进行卷积是非常通用的图像处理方法,现在的卷积神经网络就是最成功的一个应用。
传统的方法是手动选择卷积核,对于不同的卷积核,可以获得不同的结果,例如图像模糊、图像锐化或边缘检测。


使用水平边缘卷积核,可以提取一些水平直线。当然也有垂直边缘检测卷积核,可以提取一些垂直线,在字符识别和车牌识别中非常有用。

卷积及相关操作
除此之外,还有一个专题,有很多介绍。[0]

5、cv2.GaussianBlur() 高斯模糊


高斯模糊GaussianBlur()中 参数详解
prototype:
cv2.GaussianBlur( SRC,ksize,sigmaX [,DST [,sigmaY [,borderType ] ] ] ) →DST
parameter:
src 输入图像;图像可以具有任何数量的信道,其独立地处理的,但深度应CV_8U,CV_16U,CV_16S,CV_32F或CV_64F。
dst 输出与图像大小和类型相同的图像src。
ksize 高斯核大小。 ksize.width 并且 ksize.height 可以有所不同,但它们都必须是正数和奇数。或者,它们可以为零,然后从计算 sigma*。
sigma 如果sigma为非正数(负数或0)的话,就会根据ksize来自动计算sigma,计算公式为sigma = 0.3*((ksize-1)*0.5-1)+0.8

sigmaX – X方向上的高斯核标准偏差。
sigmaY – Y方向上的高斯核标准差;如果 sigmaY 为零,则将其设置为等于 sigmaX;如果两个西格玛均为零,则分别根据ksize.width 和 进行计算 ksize.height(getGaussianKernel()有关详细信息,请参见 link);完全控制的结果,无论这一切的语义未来可能的修改,建议指定所有的ksize,sigmaX和sigmaY。
borderType –像素外推方法。


在不知道用什么滤波器好的时候,优先高斯滤波 cv2.GaussianBlur(),然后均值滤波 cv2.blur()


高斯滤波器是一种线性平滑滤波器
高斯滤波是对整幅图像进行加权平均的过程,每个像素的值是通过对自身和其邻域内的其他像素值进行加权平均得到的。高斯滤波的具体操作是:用一个模板(或卷积、掩码)扫描图像中的每个像素点,将模板中心像素点的值替换为邻域内像素点的加权平均灰度值模板。
基于二维高斯函数,构造权重矩阵,然后构造高斯核,最后对每个像素进行滤波(平滑、去噪)

6、去噪

去噪分为时域去噪和频域去噪

通常的时域去噪方法是:
中值滤波: Media_Image 中值滤波的原理是拿特征区域在图像滑动,每一点(与特征区域的中点重合)的值为特征区域所覆盖的范围的中值
均值滤波: mean_image 均值滤波的原理是拿特征区域在图像滑动,每一点(与特征区域的中点重合)的值为特征区域所覆盖的范围的均值
高斯滤波: guss_image 高斯滤波的原理类似,只不过特征区域内的每个点做了加权处理,可以根据需要让哪个单元的权重大,哪个单元的权重小


频域去噪
高通滤波:让图像的高频部分通过,通常留下边缘和锐化
低通滤波:让图像的低频部分通过,通常削弱边缘,得到更平坦的图像
中通滤波:让图像的中频部分通过
高斯滤波器


关于过滤和模糊:
都属于卷积,不同滤波方式之间只有卷积核不同(针对线性滤波)

低通滤波器用于模糊,高通滤波器用于锐化
低通滤波器是让低频信号通过,图像中的边缘和噪声等价于高频部分,所以低通滤波器用于去除噪声,平滑和模糊图像。
当像素与周围像素之间的亮度差异小于某个值时,低通滤波器会平滑像素的亮度。主要用于去噪和模糊,比如高斯模糊是最常用的模糊滤波器,它是一种减弱高频信号强度的低通滤波器。
另一方面,高通滤波器用于增强图像的边缘并使其锐化。
高通滤波器(HPF)是检测图像的某个区域,然后根据像素与周围像素的亮度差值来提升该像素的亮度的滤波器。也就是说,如果一个像素比它周围的像素更突出,就会提升它的亮度。
[注:常见的噪声包括椒盐噪声和高斯噪声。椒盐噪声可以理解为图像中随机出现的斑点、黑点或白点;高斯噪声可以理解为拍照时由于光照等原因引起的噪声。 】

7、cv2.cvtColor (颜色空间转换函数)

cv2.cvtColor(p1, p2) 是颜色空间转换函数,p1是需要转换的图片,p2是转换成何种格式。
cv2.COLOR_BGR2RGB 将BGR格式转换成RGB格式
cv2.COLOR_BGR2GRAY 将BGR格式转换成灰度图片 (效果不同3、①,我也暂时不知道为啥…)

import matplotlib.pyplot as plt
import cv2
 
# cv2.imread()接口读图像,读进来直接是BGR 格式数据格式在 0~255,通道格式为(W,H,C)
img_BGR = cv2.imread('D:/z/love.jpg')           # BGR
plt.subplot(2,3,1)
plt.imshow(img_BGR)
plt.axis('off')
plt.title('BGR')

img_RGB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2RGB)        # BGR 转化为 RGB
plt.subplot(2,3,2)
plt.imshow(img_RGB)
plt.axis('off')
plt.title('RGB')
  
img_GRAY = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2GRAY)      # BGR 转化为 GRAY
plt.subplot(2,3,3)
plt.imshow(img_GRAY)
plt.axis('off')
plt.title('GRAY')

plt.subplot(2,3,4)
img_GRAY1 = plt.imshow(img_RGB, cmap='gray')           
plt.show
plt.axis('off')
plt.title('GRAY_')

plt.subplot(2,3,5)
img_GRAY1 = plt.imshow(img_GRAY, cmap='gray')
plt.show
plt.axis('off')
plt.title('GRAY_real')

结果如下:
请添加图片描述

8、灰度处理

在图像处理过程中,三个通道的数据比较复杂,所以可以先对图像进行灰度化处理。
灰度化的过程就是将每个像素点的RGB值统一成同一个值。灰度化后的图像将由三通道变为单通道,单通道的数据处理起来就会简单许多。

有关详细信息,请参见上面的最后两个图。

处理1、

img_GRAY = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2GRAY)
img_GRAY1 = plt.imshow(img_GRAY, cmap='gray')

这两个步骤一起会得到一个灰色的图像

处理2、
img = cv2.imread(‘D:/z/car.png’,cv2.IMREAD_GRAYSCALE)
运行代码发现这样竟然可以直接变成灰度图,amazing,不知道能不能直接用。


plt 画出的图像和原图有色差
opencv的颜色通道顺序为[B,G,R],而matplotlib的颜色通道顺序为[R,G,B]。
需要把R和B的位置调换一下。

进行灰度处理之后,plt显示的图片是绿色的
因为还是直接使用plt显示图像,它默认使用三通道显示图像。
在plt.imshow()添加参数:plt.imshow(img_gray,cmap=”gray”)就可以显示灰色了

不过,为什么单独使用plt.imshow(img_gray,cmap=”gray”)一点用都没有呀!!(见 5、中最后一张图)
生气并询问是否有机会。


灰度图像
指的是R=G=B,灰度图像只有256种取值可能。

灰度处理
减少在图像处理过程中的计算量。将彩色图像灰度化处理以后可从起初的0-256256256缩小到0-255这256种情况,能够大大降低运算量,这是我们在进行图像处理希望看到的。
(emm…还是不理解为啥就降低运算量了,那图片不就颜色少了)

9、cv2.Sobel()

概述: 利用Sobel算子进行图像梯度计算
使用函数 cv2.Sobel()获取图像水平、垂直 及 水平和垂直叠加方向的完整边缘信息。

Format:
cv2.Sobel(src, ddepth, dx, dy[, ksize[, scale[, delta[, borderType]]]])

parameter:
src: 输入图像
ddepth: 输出图像的深度(可以理解为数据类型),-1表示与原图像相同的深度
图像深度是指存储每个像素值所用的位数,例如cv2.CV_8U,指的是8位无符号数,取值范围为0~255,超出范围则会被截断(截断指的是,当数值大于255保留为255,当数值小于0保留为0,其余不变)。
具体还有:CV_16S(16位无符号数),CV_16U(16位有符号数),CV_32F(32位浮点数),CV_64F(64位浮点数)

dx,dy: 当组合为dx=1,dy=0时求x方向的一阶导数;当组合为dx=0,dy=1时求y方向的一阶导数(如果同时为1,通常得不到想要的结果)
ksize: (可选参数)Sobel算子的大小,必须是1,3,5或者7,默认为3。
求X方向和Y方向一阶导数时,卷积核分别为:
scale:(可选参数)将梯度计算得到的数值放大的比例系数,效果通常使梯度图更亮,默认为1
delta:(可选参数)在将目标图像存储进多维数组前,可以将每个像素值增加delta,默认为0
borderType:(可选参数)决定图像在进行滤波操作(卷积)时边沿像素的处理方式,默认为BORDER_DEFAULT

返回值:渐变图

测试①了解水平和垂直边缘信息的获取(白色省略)
例1(水平方向):

import cv2
img = cv2.imread('D:/z/gezi.png',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0)
sobelx = cv2.convertScaleAbs(sobelx)   # 转回uint8  
cv2.imshow("original",img)
cv2.imshow("x",sobelx)
cv2.waitKey()
cv2.destroyAllWindows()

结果如下所示:
请添加图片描述
例2(垂直方向):

import cv2
img = cv2.imread('D:/z/gezi.png',cv2.IMREAD_GRAYSCALE)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1)
sobely = cv2.convertScaleAbs(sobely)
cv2.imshow("original",img)
cv2.imshow("y",sobely)
cv2.waitKey()
cv2.destroyAllWindows()

结果如下:
请添加图片描述

测试②当深度值不同时:

import cv2

#载入原图
img_original=cv2.imread('D:/z/hb.png',0)
#求X方向梯度,并且输出图像一个为CV_8U,一个为CV_64F
img_gradient_X_8U=cv2.Sobel(img_original,-1,1,0)
img_gradient_X_64F=cv2.Sobel(img_original,cv2.CV_64F,1,0)

#将图像深度改为CV_8U
img_gradient_X_64Fto8U=cv2.convertScaleAbs(img_gradient_X_64F)

#图像显示
cv2.imshow('X_gradient_8U',img_gradient_X_8U)
cv2.imshow('X_gradient_64F',img_gradient_X_64F)
cv2.imshow('X_gradient_64Fto8U',img_gradient_X_64Fto8U)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果如下图所示:
例1:
请添加图片描述
例2:
请添加图片描述
(具体为啥会有这种区别,emm…时间问题暂时不展开了,如果小赵老师会而且愿意给我讲的话,我再回来给解答哈)

10、cv2.convertScaleAbs()函数

函数格式:cv2.convertScaleAbs(src[,alpha[,beta]])
Overview:
通过线性变换将数据转换成8位[uint8]
先计算数组绝对值,后转化为8位无符号数

parameter:
src:输入图像(多维数组)
alpha:比例因子
beta:保存新图像(数组)前可以增加的值

使用了函数cv2.convertScaleAbs()将图像深度为其他梯度图像重新转化为CV_8U,这是由于函数cv2.imshow()的默认显示为8位无符号数,即[0,255]

11、cv2.imshow() 显示图像

cv2.imread(图片,**cv2.IMREAD_GRAYSCALE**)
cv2.IMREAD_COLOR:默认参数,读入一副彩色图片,忽略alpha通道
cv2.IMREAD_GRAYSCALE:读入灰度图片(竟然可以直接变成灰色的)
cv2.IMREAD_UNCHANGED:顾名思义,读入完整图片,包括alpha通道

12、cv2.threshold() 简单阈值函数

阈值的作用是根据设定值对图像的灰度值进行处理。例如灰度值大于某个值,保留像素点。通过阈值和相关算法,可以从图像中捕获特定的图形,例如背景去除。

function
Python: cv2.threshold(src, thresh, maxval, type[, dst]) → retval, dst

parameter:
src:表示的是图片源
thresh:表示的是阈值(起始值)
maxval:表示的是最大值
type:表示的是这里划分的时候使用的是什么类型的算法,常用值为0(cv2.THRESH_BINARY)

cv2.THRESH_BINARY_INV
请添加图片描述
其他值为:
cv2.THRESH_OTSU
cv2.THRESH_TRIANGLE
cv2.THRESH_MASK

cv2.THRESH_BINARY 大于阈值的部分被置为255,小于部分被置为0
cv2.THRESH_BINARY_INV 大于阈值部分被置为0,小于部分被置为255
cv2.THRESH_TRUNC 大于阈值部分被置为threshold,小于部分保持原样
cv2.THRESH_TOZERO 小于阈值部分被置为0,大于部分保持不变
cv2.THRESH_TOZERO_INV 大于阈值部分被置为0,小于部分保持不变
cv2.THRESH_OTSU,并且把阈值thresh设为0,算法会找到最优阈值,并作为第一个返回值ret返回。

当使用cv2.THRESH_OTSU或cv2.THRESH_TRIANGLE时,阈值是动态的,会根据计算结果返回相应的数值。

cv2.THRESH_OTSU使用最小二乘法处理像素点
cv2.THRESH_TRIANGLE使用三角算法处理像素点。
一般情况下,cv2.THRESH_OTSU适合双峰图。cv2.THRESH_TRIANGLE适合单峰图。单峰图或者双峰图指的是灰度直方图。

13、cv2.getStructuringElement()

Opencv中函数getStructuringElement()可以生成形态学操作中用到的核,函数原型:
getStructuringElement(shape, ksize,Point anchor=Point(-1,-1));

parameter:
shape:核的形状
ksize:核的大小
Point anchor:核中心位置,默认位于形状中心处

矩形:MORPH_RECT;
交叉形:MORPH_CROSS;
椭圆形:MORPH_ELLIPSE;
第二和第三个参数分别是内核的尺寸以及锚点的位置。一般在调用erode以及dilate函数之前,先定义一个Mat类型的变量来获得

返回值:
对于锚点的位置,有默认值Point(-1,-1),表示锚点位于中心点。element形状唯一依赖锚点位置,其他情况下,锚点只是影响了形态学运算结果的偏移。

膨胀或者腐蚀操作就是将图像(或图像的一部分区域,我们称之为A)与核(我们称之为B)进行卷积。

kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (17, 5))
print(kernelX)

结果如下:
请添加图片描述

14、cv2.morphologyEx() 形态学变化函数

函数形式:dst = cv.morphologyEx(src, op, kernel)

parameter:
src: 输入图片
op:
MORPH_OPEN – 开运算(Opening operation)先腐蚀再膨胀。开运算可以用来消除小黑点,在纤细点处分离物体、平滑较大物体边界的同时并不明显改变其面积。
MORPH_CLOSE – 闭运算(Closing operation)先膨胀再腐蚀。闭运算可以用来排除小黑洞。
MORPH_GRADIENT – 形态学梯度(Morphological gradient)边缘。可以突出团块(blob)的边缘,保留物体的边缘轮廓。
MORPH_TOPHAT – 顶帽(Top hat)突出亮区。突出比原轮廓亮的部分。
MORPH_BLACKHAT – 黑帽(Black hat)突出暗区。将突出比原轮廓暗的部分。
MORPH_ERODE – 腐蚀 (erode)
MORPH_DILATE – 膨胀 (dilate)
kernel: 利用cv2.getStructuringElement()函数构造

15、开运算、闭运算

开闭运算就是按照一定的顺序处理腐蚀和膨胀。但这两者是不可逆的,即先开合不能得到原图。
闭运算用于将被错误分类的物体连接成许多小块,而开运算用于去除图像噪声形成的散斑。

开运算可用于去除小黑点、在细点处分离对象以及平滑较大对象的边界而不显着改变其面积。
闭合操作可用于排除小黑洞。

因此,在某些情况下,这两个操作可以连续使用。如果在二值图像上依次使用闭运算和开运算,将得到图像中的主要对象。同样,如果要去除图像中的噪点(即图像中的“小点”),也可以打开然后关闭图像,但这也会去除一些破碎的物体。

16、cv2.dilate()、cv2.erode() 膨胀和腐蚀

这里有更详细的介绍:Morphological Image Processing: Dilation and Erosion
膨胀和腐蚀可以执行多种功能,主要如下:
消除噪声;分割(isolate)出独立的图像元素,在图像中连接(join)相邻的元素;寻找图像中的明显的极大值区域或极小值区域;求出图像的梯度。[0]

腐蚀和膨胀适用于白色部分(高光),而不是黑色部分。 Dilation 是对图像高亮部分的扩大,“场扩大”,渲染出来的高亮区域比原图更大。腐蚀是指原图的高亮部分被腐蚀,“场被侵蚀”,效果图的高亮区域比原图小。

膨胀是寻找局部最大值的操作,腐蚀是寻找局部最小值的操作。

使用erode函数,一般我们只需要填前面的三个参数,后面的四个参数都有默认值。而且往往结合getStructuringElement一起使用。

import cv2
import numpy as np

img = cv2.imread('D:/binary.bmp',0)
#OpenCV定义的结构元素
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3))
 
#腐蚀图像
eroded = cv2.erode(img,kernel)
#显示腐蚀后的图像
cv2.imshow("Eroded Image",eroded);
 
#膨胀图像
dilated = cv2.dilate(img,kernel)
#显示膨胀后的图像
cv2.imshow("Dilated Image",dilated);
#原图像
cv2.imshow("Origin", img)
 
#NumPy定义的结构元素
NpKernel = np.uint8(np.ones((3,3)))
Nperoded = cv2.erode(img,NpKernel)
#显示腐蚀后的图像
cv2.imshow("Eroded by NumPy kernel",Nperoded);
 
cv2.waitKey(0)
cv2.destroyAllWindows()

结果如下:
请添加图片描述

17、cv2.findContours()查找轮廓,cv2.drawContours() 绘制轮廓

cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图),所以读取的图像要先转成灰度的,再转成二值图

功能形式:(找轮廓)
cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]])

parameter:
image: 输入图像
mode: 表示轮廓的检索模式,有四种:
cv2.RETR_EXTERNAL表示只检测外轮廓
cv2.RETR_LIST检测的轮廓不建立等级关系
cv2.RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
cv2.RETR_TREE建立一个等级树结构的轮廓。
method: 轮廓的近似办法
cv2.CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1
cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
cv2.CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法

返回值:
contours: 一个列表,每一项都是一个轮廓, 不会存储轮廓所有的点,只存储能描述轮廓的点
hierarchy: 一个ndarray, 元素数量和轮廓数量一样, 每个轮廓contours [ i ] 对应4个hierarchy元素hierarchy [i] [0] ~ hierarchy[i][3],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,则该值为负数。

功能形式:(画轮廓)
cv2.drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None)

parameter:
image: 指明在哪幅图像上绘制轮廓。image为三通道才能显示轮廓
contours: 轮廓本身,在Python中是一个list
contoursldx: 指定绘制轮廓list中的哪条轮廓,如果是 -1,则绘制其中的所有轮廓。
thickness: 表明轮廓线的宽度,如果是-1(cv2.FILLED),则为填充模式。
lineType: 线型
hierarchy: 轮廓结构信息

18、cv2.boundingRect()

用一个最小的矩形包裹找到的形状。

函数形式:cv2.boundingRect(img) –>(x, y, w, h)

参数:img是一个二值图

返回四个值,分别是x,y,w,h;
x,y是矩阵左上点的坐标,w,h是矩阵的宽和高

然后利用cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2) 画出矩形
参数说明
第一个参数:img是输入图像
第二个参数:(x,y)是矩阵的左上点坐标
第三个参数:(x+w,y+h)是矩阵的右下点坐标
第四个参数:(0,255,0)是画线对应的rgb颜色
第五个参数:2是所画的线的宽度

import cv2
import matplotlib.pyplot as plt
img = cv2.imread('D:/z/hb.png')

x,y,w,h = cv2.boundingRect(img)
cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)
plt.imshow(img)

运行结果…
请添加图片描述
我哭了。。。怎么不行。。。
我什至不知道为什么,但就是这样,这让我很生气! ! !
小赵老师理理我吧,孩子敲不下去了T_T

19、for in 循环

一种循环结构,常用于遍历字符串、列表、元组、字典等。
Format:

for x in y:
	循环体

实施过程:
x 依次表示 y 中的一个元素,遍历完所有元素循环结束

20、image.shape

输出三个参数
(高度、宽度、通道数)
image.shape[0], 图片高
image.shape[1], 图片宽
image.shape[2], 图片通道数

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
xiaoxingxing的头像xiaoxingxing管理团队
上一篇 2022年4月27日 下午10:50
下一篇 2022年4月27日

相关推荐