刚开始接触OpenCV是因为需要进行图像的处理,由于之前没有接触过,所以只能自己进行学习,下面将学习的过程做简单记录分享。
OpenCV专栏链接
OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉库,提供了丰富的图像处理和计算机视觉算法。它广泛应用于图像处理、人脸识别、目标检测、机器视觉等领域。学习OpenCV编程语言对于计算机视觉领域的开发人员来说非常重要。
在开始学习OpenCV编程之前,需要先安装OpenCV库和相应的基本操作。
pip install opencv-python
pip install opencv-contrib-python
img = cv.imread("a.jpg")
cv.imshow("img", img)
#导入cv模块
import cv2 as cv
#读取图片
img = cv.imread("a.jpg")
#显示图片
cv.imshow("read_img",img)
#等待
cv.waitKey(0)
#释放内存
cv.destroyAllWindows()
运行结果:
gray_img = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
resize_img = cv.resize(img, dsize=(200, 200))
cv.rectangle(img, (x, y, x + w, y + h), color=(0, 0, 255), thickness=1)
cv.circle(img, center=(x + w, y + h), radius=100, color=(255, 0, 0), thickness=2)
cv.imread()
1:彩色图像
0 :灰度图像
-1:alpha通道图像
cv.imshow()/plt.imshow()
参数:
注意:要调用**cv.waitKey()**给图像绘制留下时间,否则窗口会出现无响应情况,并且图像无法显示出来。
cv.imwrite()
参数:文件名 要保存在哪里 要保存的图像
cv.line(img,start,end,color,thickness)
参数:
cv.circle(img, centerpoint, r, color, thickness)
参数:
cv.rectangle(img, leftupper, rightdown, color, thickness)
参数:
cv.putText(img, text, startion, font, fontsize, color, thickness, cv.LINE_AA)
参数:
#导入cv模块
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
# 1 创建一个空白的图像
img = np.zeros((512, 512, 3), np.uint8)
# 2 绘制图像
cv.line(img, (0, 0), (511, 511), (255, 0, 0), 5)
cv.rectangle(img, (384, 0), (510, 128), (0, 255, 0), 3)
cv.circle(img, (447, 63), 63, (0, 0, 255), -1)
font = cv.FONT_HERSHEY_SIMPLEX
cv.putText(img, "OpenCv", (10, 500), font, 4, (255, 255, 255), 2, cv.LINE_AA)
plt.imshow(img[:, :, ::-1])
plt.show()
使用cv.add()函数将两幅图像相加(或者简单通过Numpy操作添加两个图像),两个图像应该具有相同的大小和类型,或者第二个图像可以是标量值。
区别:
两个图像的权重不同
图像混合的计算公式如下:
g(x)=(1-α) f0(x)+α f1(x)
通过修改α的值(0–>1)实现炫酷的组合图。
函数cv.addWeighted()可以按下面的公式进行混合操作:
dst= α img1+β img2+Y
cv2.resize(src,dsize,fx=0,fy=0,interpolation=cv2,INTER_LINEAR)
参数:
插值 | 含义 |
---|---|
INTER_LINEAR | 双线性插值 |
INTER_NEAREST | 最近邻插值 |
INTER_AREA | 像素区域重采样 |
INTER_CUBIC | 双三次插值 |
cv.warpAffine(img, M, dsize)
参数:
注意:
在OpenCV中图像旋转首先根据旋转角度和旋转中心获取旋转矩阵,然后根据旋转矩阵进行变换,即可实现任意角度和任意中心的旋转效果。
API:
cv2.getRotationMatrix2D(center, angle, scale)
由于图像采集、处理、传输等过程不可避免的会受到噪声的污染,妨碍人们对图像理解及分析处理。常见的图像噪声有高斯噪声、椒盐噪声等。
椒盐噪声也称为脉冲噪声,是图像中经常见到的一种噪声,它是一种随机出现的白点或者黑点,可能是亮的区域有黑色像素或是在暗的区域有白色像素,或是两者皆有。
椒盐噪声的成因可能是影像讯号受到突如其来的强烈干扰而产生、类比数位转换器或位元传输错误等。例如失效的感应器导致像素值为最小值,饱和的感应器导致像素值为最大值。
高斯噪声是指噪声密度函数服从高斯分布的一类噪声。
图像平滑从信号处理的角度看就是去除其中的高频信息,保留低频信息。因此我们可以对图像实施低通滤波。低通滤波可以去除图像中的噪声,对图像进行平滑。
根据滤波器的不同可分为均值滤波,高斯滤波,中值滤波,双边滤波。
采用均值滤波模板对图像噪声进行滤除。令Pay表示中心在(x,y)点,尺寸为mxn的矩形子图像窗口的坐标组。均值滤波器可表示为:
由一个归一化卷积框完成的。它只是用卷积框覆盖区域所有像素的平均值来代替中心元素。
API:
cv.blur(src, ksize, anchor, borderType )
参数:
示例:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 解决中文显示问题
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 1图像读取
img = cv. imread('./images/d1.jpg')
# 2均值滤波
blur = cv.blur(img, (5, 5))
# 3图像显示
plt.figure(figsize=(10, 8), dpi=100)
plt.subplot(121), plt.imshow(img[:, :, ::-1]), plt.title('原图')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(blur[:, :, ::-1]), plt.title('均值波后结果')
plt.xticks([]), plt.yticks([])
plt.show()
二维高斯是构建高斯滤波器的基础.
API:
cv2.GaussianBlur(src, ksize,sigmaX,sigmay, borderType )
参数:
示例:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 解决中文显示问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 1图像读取
img = cv.imread('./images/d2.jpg')
# 2高斯滤波
blur = cv.GaussianBlur(img, (3, 3), 1)
# 3图像显示
plt.figure(figsize=(10, 8), dpi=100)
plt.subplot(121), plt.imshow(img[:, :, ::-1]), plt.title("原图")
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(blur[:, :, ::-1]), plt.title("高斯滤波后结果")
plt.xticks([]), plt.yticks([])
plt.show()
中值滤波是一种典型的非线性滤波技术,基本思想是用像素点邻域灰度值的中值来代替该像素点的灰度值。
中值滤波对椒盐噪声(salt-and-pepper noise)来说尤其有用,因为它不依赖于邻域内那些与典型值差别很大的值。
API:
cv.medianBlur(src, ksize)
参数:
示例:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 解决中文显示问题
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 1图像读取
img = cv.imread('./images/d3.jpg.jpg')
# 2中值速波
blur = cv.medianBlur(img, 5)
# 3图像展示
plt.figure(figsize=(10, 8), dpi=100)
plt.subplot(121), plt.imshow(img[:, :, ::-1]), plt.title("原图")
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(blur[:, :, ::-1]), plt.title("中值滤波后结果")
plt.xticks([]), plt.yticks([])
plt.show()
边缘检测是图像处理和计算机视觉中的基本问题,边缘检测的目的是标识数字图像中亮度变化明显,图像属性中的显著变化通常反映了属性的重要事件和变化。
图像边缘检测大幅度地减少了数据量,并且剔除了可以认为不相关的信息,保留了图像重要的结构属性。有许多方法用于边缘检测,它们的绝大部分可以划分为两类:基于搜索和基于零穿越。
基于搜索:通过寻找图像一阶导数中的最大值来检测边界,然后利用计算结果估计边缘的局部方向,通常采用梯度的方向,并利用此方向找到局部梯度模的最大值,代表算法是Sobel算子和Scharr算子。
基于零穿越:通过寻找图像二阶导数零穿越来寻找边界,代表算法是Laplacian算子。
Sobeli边缘检测算法比较简单,实际应用中效率比canny边缘检测效率要高,但是边缘不如Canny检测的准确,但是很多实际应用的场合,sobel边缘却是首选,sobel算子是高斯平滑与微分操作的结合体,所以其抗噪声能力很强,用途较多。尤其是效率要求较高,而对细纹理不太关心的时候。
sobel边缘检测的API是:
Sobel_x_or_y = cv2.Sobel(src,ddepth,dx,dy,dst,ksize,scale,delta,borderType)
参数:
Sobel算子是在两个方向计算的,最后还需要用cv2.addWeighted()函数将其组合起来。
Scale_abs = cv2.convertScaleAbs(x)#格式转换
result = cv2.addWeighted(src1,alpha,src2,beta)#图像混合
示例:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 解决中文显示问题
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 1读取图像
img = cv.imread('./images/ma.jpg',0)
# 2计算Sobel卷积结果
x = cv.Sobel(img, cv.CV_16S, 1, 0)
y = cv.Sobel(img, cv.CV_16S, 0, 1)
# 3将数据进行转换
# convert转换 scale缩放
Scale_absX = cv.convertScaleAbs(x)
Scale_absY = cv.convertScaleAbs(y)
# 4结果合成
result = cv.addWeighted(Scale_absX, 0.5, Scale_absY, 0.5, 0)
# 5图像显示
plt.figure(figsize=(10, 8), dpi=100)
plt.subplot(121), plt.imshow(img, cmap=plt.cm.gray), plt.title("原图")
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(result, cmap=plt.cm.gray), plt.title("Sobel滤波后结果")
plt.xticks([]), plt.yticks([])
plt.show()
Laplacian是利用二阶导数来检测边缘。
АРI:
laplacian = cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])
参数:
示例:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 解决中文显示问题
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 1读取图像
img = cv.imread('./images/ma.jpg', 0)
# 2laplacian转换
result = cv.Laplacian(img, cv.CV_16S)
Scale_abs = cv.convertScaleAbs(result)
# 3图像展示
plt.figure(figsize=(10, 8), dpi=100)
plt.subplot(121), plt.imshow(img, cmap=plt.cm.gray), plt.title('原图')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(Scale_abs, cmap=plt.cm.gray), plt.title('Laplacian检测后结果')
plt.xticks([]), plt.yticks([])
plt.show()
Canny边缘检测算法是一种非常流行的边缘检测算法,是John F.Canny于1986年提出的,被认为是最优的边缘检测算法。
API:
canny = cv2.Canny(image, threshold1, threshold2)
参数:
示例:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 解决中文显示问题
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 1读取图像
img = cv.imread('./images/ma.jpg', 0)
# 2Canny边缘检测
lowThreshold = 0
max_lowThreshold = 100
canny = cv.Canny(img, lowThreshold, max_lowThreshold)
# 3图像展示
plt.figure(figsize=(10, 8), dpi=100)
plt.subplot(121), plt.imshow(img, cmap=plt.cm.gray), plt.title('原图')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(canny, cmap=plt.cm.gray), plt.title('Canny检测后结果')
plt.xticks([]), plt.yticks([])
plt.show()
模板匹配:在给定的模板中查找最相似的区域
实现流程:
OpenCV中的方法实现模板匹配。
API:
res = cv.matchTemplate(img, template,method)
参数:
import cv2 as cv
import matplotlib.pyplot as plt
# 解决中文显示问题
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 1图像和模板读取
img = cv.imread('images/wulin.jpg')
template = cv.imread('images/wulinmoban.jpg')
# 2模板匹配
# 2.1模板匹配
res = cv.matchTemplate(img, template, cv.TM_CCORR)
# 2.2返回图像中最匹配的位置,确定左上角的坐标,并将匹配位置绘制在图像上
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res)
# 使用平方差时最小值为最佳匹配位置
# top_left = min_loc
top_left = max_loc
h, w = template.shape[:2]
bottom_right = (top_left[0] + w, top_left[1] + h)
cv.rectangle(img, top_left, bottom_right, (0, 255, 0), 2)
# 3图像显示
plt.imshow(img[:, :, ::-1])
plt.title('匹配结果'),plt.xticks([]),plt.yticks([])
plt.show()
cv.HoughLines(img, rho, theta, threshold)
参数:
import numpy as np
import random
import cv2 as cv
import matplotlib.pyplot as plt
#1.加载图片,转为二值图
img = cv.imread('images/rili.jpg')
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray, 50, 150)
#2.霍夫直线变换
lines = cv.HoughLines(edges, 0.8, np.pi / 180, 150)
#3.将检测的线绘制在图像上(注意是极坐标噢)
for line in lines:
rho, theta = line[0]
a = np.cos(theta)
b = np.sin(theta)
x0=a * rho
y0=b * rho
x1 = int(x0+1000*(-b))
y1 = int(y0+1000*a)
x2 = int(x0-1000*(-b))
y2 = int(y0-1000*a)
cv.line(img, (x1, y1), (x2, y2), (0, 255, 0))
#4.图像显示
plt.figure(figsize=(10, 8), dpi=100)
plt.imshow(img[:, :, ::-1]), plt.title('霍夫变换线检测')
plt.xticks([]), plt.yticks([])
plt.show()
在OpenCV中检测图像中的圆环使用的是API是:
v.HoughCircles(image, method, dp, minDist, paraml=100, param2=100, minRadius=0,maxRadius=0
参数:
返回:
1.模板匹配
原理:在给定的图片中查找和模板最相似的区域
API:利用cv.matchTemplate0进行模板匹配,然后使用cv.minMaxLoc0搜索最匹配的位置。
2.霍夫线检测
原理:将要检测的内容转换到霍夫空间中,利用累加器统计最优解,将检测结果表示处理
API: cv2.HoughLines
注意:该方法输入是的二值化图像,在进行检测前要将图像进行二值化处理
3.霍夫圆检测
方法:霍夫梯度法
在OpenCV中我们要获取一个视频,需要创建一个VideoCapture对象,指定你要读取的视频文件:
cap = cv.VideoCapture(filepath)
参数:
(1)获取视频的某些属性
retval = cap.get(propId)
参数:
常用属性有:
flags | 意义 |
---|---|
cv2.CAP_PROP_POS_MSEC | 视频文件的当前位置(ms) |
cv2.CAP_PROP_POS_FRAMES | 从0开始索引帧,帧位置 |
cv2.CAP_PROP_POS_AVI_RATIO | 视频文件的相对位置(0表示开始,1表示结束) |
cv2.CAP_PROP_FRAME_WIDTH | 视频流的帧宽度 |
cv2.CAP_PROP_FRAME_HEIGHT | 视频流的帧高度 |
cv2.CAP_PROP_FPS | 帧率 |
cv2.CAP_PROP_FOURCC | 编解码器四字符代码 |
cv2.CAP_PROP_FRAME_COUNT | 视频文件的帧 |
(2)修改视频的属性信息
cap.set(propId, value)
参数:
(3)判断图像是否读取成功
isornot = cap.isOpened()
(4)获取视频的一帧图像
ret, frame = cap.read()
参数:
调用cv.imshow0显示图像,在显示图像时使用cv.waitkey0设置适当的持续时间,如果太低视频会播放的非常快,如果太高就会播放的非常慢,通常情况下我们设置25ms就可以了。
最后,调用cap.realease0将视频释放掉。
示例:
import numpy as np
import cv2 as cv
#1.获取视频对象
cap = cv.VideoCapture('路径')
#2.判断是否读取成功
while(cap.isOpened()):
#3.获取每一帧图像
ret, frame = cap.read()
#4.获取成功显示图像
if ret == True:
cv.imshow('frame',frame)
#5.每一帧间隔为25ms
if cv.waitKey(25)& 0xFF == ord('q'):
break
#6.释放视频对象
cap.release()
cv.destoryAllwindows()
在OpenCV中我们保存视频使用的是VedioWriter对象,在其中指定输出文件的名称,如下所示:
out = cv2.VideoWriter(filename,fourcc, fps, frameSize)
参数:
retval = cv2.Videowriter_fourcc( c1, c2, c3, c4 )
参数:
c1,c2,c3,c4:是视频编解码器的4字节代码。
常用的有:
在Windows中:DIVX(.avi)
在OS中:MJPG(.mp4),DIVX(.avi),X264(.mkv)。
利用cap.read0获取视频中的每一帧图像,并使用out.write(将某一帧图像写入视频中。
使用cap.release0和out.release(释放资源。
示例:
import cv2 as cv
import numpy as np
#1.读取视频
cap = cv.VideoCapture("路径")
#2.获取图像的属性(宽和高,),并将其转换为整数
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
#3.创建保存视频的对象,设置编码格式,帧率,图像的宽高等
out = cv.Videowriter('outpy.avi',cv.Videowriter_fourcc('M','J','P','G'), 10,(frame_width,frame_height))
while(True):
#4.获取视频中的每一帧图像
ret, frame = cap.read()
if ret == True:
#5.将每一帧图像写入到输出文件中
out.write(frame)
else:
break
#6.释放资源
cap.release()
out.release()
cv.destroyAllWindows()
from PIL import Image
ascii_char = list('"$%_&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-/+@<>i!;:,\^`.')
def get_char(r, b, g, alpha=256):
if alpha == 0:
return ' '
gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
unit = 256 / len(ascii_char)
return ascii_char[int(gray//unit)]
def main():
im = Image.open('A.jpg')
WIDTH, HEIGHT = 100, 60
im = im.resize((WIDTH, HEIGHT))
txt = ""
for i in range(HEIGHT):
for j in range(WIDTH):
txt += get_char(*im.getpixel((j, i)))
txt += '\n'
fo = open("A.txt","w")
fo.write(txt)
fo.close()
main()
学习OpenCV编程语言对于计算机视觉领域的开发人员来说非常重要。通过掌握OpenCV的基础知识、函数和控制流程、面向对象编程等技术,可以更好地应用于图像处理、人脸识别、目标检测、机器视觉等领域。未来,随着计算机视觉技术的不断发展,OpenCV将会发挥更加重要的作用。