深度学习|opencv基本操作

layout: _posts
title: opencv基本操作(1).md
date: 2021-09-16 23:08:24
tags:

本贴记录,总结opencv,的使用与安装。也给来的朋友做一个参考作用
1.先安装opencv和相应版本的opencv-contrib-python
pip install opencv-python pip install opencv-contrib-python=='版本号'

2.开始教程 1.图片和视频的读取和显示保存 1.使用opencv读取相应的图片
代码:
import cv2 import numpy as np import matplotlibtu.pyplot as pltimg = cv2.imread("F:/images/1.jpg") # 读取的img为一个numpy数组

相应的可以使用 img.shape 来查看数组的形状,也可以使用
图片的显示:
# 'result'参数表示窗口的名称 cv2.imshow('result',img) cv2.waitKey(0) cv2.destroyAllWindows()

此时的waitkey中的参数可以为0,或者其他,为0时表示按任意键退出,而填写其他数时表示图片窗口的持续时间
可以将编写一个显示函数进行替代:
def cv_show(name,img): cv2.show(name,img) cv2.waitKey(0) cv2.destroyAllWindows()

2.读取相应的灰度图
img = cv2.imread('F:/images/1.jpg',cv2.IMGREAD_GRAYSCALE)

3. 图片的保存
cv2.imwrite('F:/images/save_picture.jpg',img)

4.视频的读取
vc = Cv2.videoCapture('F:/images/2.mp4') if vc.isOpened(): open, frame = vc.read() else: open = Falsewhile open: ret, frame = vc.read() if frame is None: break if ret == True: # 将每一帧的图像都转化为灰度图 gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) cv2.imshow('result',frame) if cv2.waitKey(10) & 0xFF == 27: break cv2.release() cv2.destroyAllWindows()

2.图片的处理 1.截取图片的指定位置
img = cv2.imread('F:/images/1.jpg') car = img[:200,:200] cv_show('result',car)

2.对图片色道的拆分与合并
b, g, r = cv2.split(img) img = cv2.merge((b, g, r)) # 也可以这样操作 b = img[:,:,0] g = img[:,:,1] r = img[:,:,2] # 将三种通道单独显示 cur_img = img.copy() cur_img_b[:,:,1] = 0 cur_img_b[:,:,2] = 0 plt.subplot(231), plt.imshow(cur_img_b)cur_img_g[:,:,0] = 0 cur_img_g[:,:,2] = 0 plt.subplot(232), plt.imshow(cur_img_g) cur_img_r[:,:,0] = 0 cur_img_r[:,:,1] = 0 plt.subplot(233), plt.imshow(cur_img_r)

3.边界填充
# 设置四周的填充大小 top_size, bottom_size, left_size, right_size = (100,100,100,100) replicate = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_REPLICATE) reflect = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_REFLECT) reflect101 = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_REFLECT_101) wrap = cv2.copyMakeBoder(img,top_size, bottom_size, left_size, right_size, cv2.BORDER_WRAP) constant = cv2.copyMakeBoder(img, top_size, bottom_size, left_size, right_size, BORDER_CONSTANT,value = https://www.it610.com/article/0)

  • relicate:对边界进行复制填充
  • reflect:对图片的两边的像素进行反射
  • refect101:以边缘为轴进行反射
  • wrap:对四周进行重复填充
  • constant:对照片进行常数填充
    将几种填充显示出来 import matplotlib.pyplot as plt plt.subplot(231), plt.imshow(img),plt.title('original') plt.subplot(232), plt.imshow(replicate),plt.title('replicate') plt.subplot(233), plt.imshow(reflect),plt.title('reflect') plt.subplot(234), plt.imshow(reflect101), plt.title('reflect101') plt.subplot(235), plt.imshow(wrap), plt.title('wrap') plt.subplot(236), plt.imshow(constant), plt.title('constant')

    BORDER_REPLICATE:复制法,也就是复制最边缘的像素 BORDER_REFLECT:反射法,对感兴趣的图像中的像素在两边进行复制,如fedcba|abcdefgh|hgfedcb BORDER_REFLECT_101:反射法,也就是以边缘为轴,对称如:hgfedc|abcdefgh|fedcba BORDER_WRAP:外包装法cdefgh|abcdefgh|abcdefg BORDER_CONSTANT:常数法,使用常数值进行填充

4.数值计算
# 图片的读入 img_car = cv2.imread('F:/images/1.jpg') img_car2 = img_car+10 cv_show('result',img_car2)

  1. 直接对读取出来的图片进行直接相加
# 该方式会对于图片中的像素点像素值高于255进行取余计算 img_car+img_car2

  1. 使用opencv中的add函数
# 该方法对于像素点像素值高于255按255计算 cv2.add(img_car,img_car2)

5.图像融合
# 对图像进行读取 img_car = cv2.imread('F:/images/1.jpg') img_cat = cv2.imread('F:/images/3.jpg') # 使用cv2.addWeighted() res = cv2.addWeighted(img_cat,0.6,img_car,0.3,0) # 将两张不同的图片按比例进行融合,谁的比重小谁更明显,对于融合后的像素点高于255的也是进行取余计算

6.图片形状的改变
# 使用官方的cv2.resize()函数 res = cv2.resize(img,(0,0),fx=4,fy=3) plt.imshow(res) plt.show() # 此处的(0,0)指输出图片的尺寸,为零时指按图片的大小来进行缩放

3.图像的阈值和平滑处理 1.图像的阈值操作
res, dst = cv2.threshold(src,thresh,maxval,type)
src:输入图,只能输入单通道图像,通常为灰度图
dst:输出图
threash:阈值
maxval:当像素超过了阈值或者小于阈值,根据type来决定所赋予的值
type:二值化操作的类型,包括以下五种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO; cv2.THRESH_TOZERO_INV
cv2.THRESH_BINARY:超过阈值取maxval,否则则取0
cv2.THRESH_BINARY_INV:THRESH_BINARY的反转
cv2.THRESH_TRUNC:大于阈值部分设为阈值,否则不变
cv2.THRESH_TOZERO:大于阈值部分不变,否则设为0
cv2.THRESH_TOZERO_INV:THRESH_TOZERO的反转
img_gray = cv2.imread('F:/images/1.jpg',cv2.IMREAD_GRAYSCALE) img = cv2.imread('F:/images/1.jpg') ret, thresh1 = cv2.threshold(img_gray,127,255,cv2.THRESH_BINARY) ret, thresh2 = cv2.threshold(img_gray,127,255,cv2.THRESH_BINARY_INV) ret, thresh3 = cv2.threshold(img_gray,127,255,cv2.THRESH_TRUNC) ret, thresh4 = cv2.threshold(img_gray,127,255,cv2.THRESH_TOZERO) ret, thresh5 = cv2.threshold(img_gray,127,255,cv2.THRESH_TOZERO_INV)titles = ['ORIGINAL','THRESH_BINARY','THRESH_BINARY_INV','THRESH_TRUNC','THRESH_TOZERO','THRESH_TOZERO_INV'] images = [img,thresh1,thresh2,thresh3,thresh4,thresh5] for i in range(6): plt.subplot(2,3,i+1),plt.imshow(images[i]) plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()

2. 平滑处理
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread('F:/images/4.jpg') cv2.imshow('result',img) cv2.waitKey(0) cv2.destroyAllWindows()

1.方框滤波
box = cv2.boxFilter(img,-1,(3,3),normalize=True)# 区别,当normalize为True时,和均值滤波相同,而为False时,则不做归一化操作,对于高于255的按255算box1 = cv2.boxFilter(img,-1,(3,3),normalize=False) plt.subplot(121),plt.imshow(box) plt.subplot(122),plt.imshow(box1) plt.show()

2. 高斯滤波
aussian = cv2.GaussianBlur(img,(5,5),1) plt.imshow(aussian) plt.show()

3.中值滤波
# 对于带有噪点的图片中值滤波的优化效果最明显 median = cv2.medianBlur(img,5) plt.imshow(median) plt.show()

4.总结对比,将图片放到一起比较
res = np.hstack((img,blur,box,aussian,median)) # cv2.imshow('result',res) # cv2.waitKey(0) # cv2.destroyAllWindows() plt.imshow(res) plt.show()

3.图像的形态学操作
# 图片和模块的导入 import cv2 import matplotlib.pyplot as plt import numpy as npimg = cv2.imread('F:/images/5.jpg') plt.imshow(img) plt.show()

1.腐蚀操作
# 腐蚀操作一般用于二值数据的图 kernel = np.array([[0.5,0.5,0.5],[1,1,1],[2,2,2]]) # kernel = np.ones((5,5)) erosion = cv2.erode(img,kernel,iterations = 1) plt.imshow(erosion) plt.show()

2.膨胀操作
img = cv2.imread('F:/images/5.jpg') kernel = np.ones((2,2),dtype = np.uint8) erosion = cv2.erode(img,kernel,iterations = 1) fig = plt.figure(figsize = (10,15)) plt.subplot(121), plt.imshow(erosion) img_dilate = cv2.dilate(erosion,kernel,iterations = 3) plt.subplot(122),plt.imshow(img_dilate) plt.show()

3.开预算与闭运算
1.开运算:先腐蚀再膨胀
img = cv2.imread('F:/images/5.jpg') kernel = np.ones((3,3),dtype = np.int8) opening = cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel) # cv2.imshow('opening',opening) # cv2.waitKey(0) # cv2.destroyAllWindows() plt.imshow(opening) plt.show()

2. 闭运算:先膨胀再腐蚀
closing = cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel) plt.imshow(closing) plt.show()

4.梯度运算
# 梯度运算:膨胀-腐蚀 kernel = np.ones((2,2),dtype = np.uint8) img_erosion = cv2.erode(img,kernel,iterations = 2) img_dilate = cv2.dilate(img,kernel,iterations = 2) plt.subplot(131),plt.imshow(img_erosion) plt.subplot(132),plt.imshow(img_dilate) res = img_dilate - img_erosion plt.subplot(133),plt.imshow(res) plt.show()result = np.hstack((img_erosion,img_dilate,res)) cv2.imshow('result',result) cv2.waitKey(0) cv2.destroyAllWindows() # 通过梯度运算可以得到图像的轮廓

5.礼帽与黑帽
  • 礼帽:原始 - 开运算结果
  • 黑帽:闭运算 - 原始
# 礼帽 kenel = np.ones((3,3),dtype = np.unit8) tophat = cv2.morphology(img,cv2.MORPH_TOPHAT,kenel) plt.imshow() plt.show()

# 黑帽 kernel = np.ones((3,3),dtype=np.uint8) blackhat = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel) plt.imshow(blackhat) plt.show()

4. 图像的梯度计算 1、图像和库的导入
import cv2 import numpy as np import matplotlib.pyplot as pltdef cv_show(name,image): cv2.namedWindow(name,cv2.WINDOW_NORMAL) cv2.imshow(name,image) cv2.waitKey(0) cv2.destroyAllWindows()

2.sobel算子
深度学习|opencv基本操作
文章图片

深度学习|opencv基本操作
文章图片
深度学习|opencv基本操作
文章图片

深度学习|opencv基本操作
文章图片

深度学习|opencv基本操作
文章图片

dst = cv2.Sobel(src,ddepth,dx,dy,ksize)
  • ddpeth:图像的深度
  • dx,dy:分别表示水平和竖直方向
  • ksize是sobel算子的大小
# 不对sobel_X,sobel_y做绝对值操作,且不传入灰度图后的结果 img = cv2.imread('F:/images/3.jpg') sobel_x = cv2.Sobel(img,cv2.CV_64F,1,0,ksize = 3) sobel_y = cv2.Sobel(img,cv2.CV_64F,0,1,ksize = 3) sobel_xy = cv2.Sobel(img,cv2.CV_64F,1,1,ksize = 3) res1 = cv2.addWeighted(sobel_x,0.5,sobel_y,0.5,0) res2 = sobel_x+sobel_y # cv_show('oranginal',img) # cv_show('sobel_X',res) plt.subplot(231),plt.imshow(img) plt.subplot(232),plt.imshow(sobel_x) plt.subplot(233),plt.imshow(sobel_y) plt.subplot(234),plt.imshow(res1) plt.subplot(235),plt.imshow(sobel_xy) plt.subplot(236),plt.imshow(res2) plt.show()

img = cv2.imread('F:/images/3.jpg', cv2.IMREAD_GRAYSCALE) sobel_x = cv2.Sobel(img,cv2.CV_64F,1,0,ksize = 3) sobel_y = cv2.Sobel(img,cv2.CV_64F,0,1,ksize = 3) sobel_xy = cv2.Sobel(img,cv2.CV_64F,1,1,ksize = 3) res1 = cv2.addWeighted(sobel_x,0.5,sobel_y,0.5,0) res2 = sobel_x+sobel_y # cv_show('oranginal',img) # cv_show('sobel_X',res) plt.subplot(231),plt.imshow(img) plt.subplot(232),plt.imshow(sobel_x) plt.subplot(233),plt.imshow(sobel_y) plt.subplot(234),plt.imshow(res1) plt.subplot(235),plt.imshow(sobel_xy) plt.subplot(236),plt.imshow(res2) plt.show() # 从白到黑正数,而从黑到白为负数,所有的负数将会被截断成0,所以要取绝对值

img = cv2.imread('F:/images/3.jpg',cv2.IMREAD_GRAYSCALE) sobel_x = cv2.Sobel(img,cv2.CV_64F,1,0,ksize = 3) sobel_x = cv2.convertScaleAbs(sobel_x) sobel_y = cv2.Sobel(img,cv2.CV_64F,0,1,ksize = 3) sobel_y = cv2.convertScaleAbs(sobel_y) sobel_xy = cv2.Sobel(img,cv2.CV_64F,1,1,ksize = 3) sobel_xy = cv2.convertScaleAbs(sobel_xy) res1 = cv2.addWeighted(sobel_x,0.5,sobel_y,0.5,0) res2 = sobel_x+sobel_y # cv_show('oranginal',img) # cv_show('sobel_X',res) plt.subplot(231),plt.imshow(img) plt.subplot(232),plt.imshow(sobel_x) plt.subplot(233),plt.imshow(sobel_y) plt.subplot(234),plt.imshow(res1) plt.subplot(235),plt.imshow(sobel_xy) plt.subplot(236),plt.imshow(res2) plt.show()

对于ddpeth参数:
  • CV_64FC1: 一个像素点占有64位浮点数,单通道,如灰度图
  • CV_64FC3:一个像素点占有64位浮点数,四通道,如带有alpha的rgb图像
  • CV_32FC1:一个像素点占有32位浮点数,单通道
  • CV_32FC3:一个像素点占有32位浮点数,四通道
Sobel算子算法的优点是计算简单,速度快。但是由于只采用了2个方向的模板,只能检测水平和垂直方向的边缘,因此这种算法对于纹理较为复杂的图像,其边缘检测效果就不是很理想。该算法认为:凡灰度新值大于或等于阈值的像素点时都是边缘点。这种判断欠合理,会造成边缘点的误判,因为许多噪声点的灰度值也很大。
3.Scharr算子
【深度学习|opencv基本操作】深度学习|opencv基本操作
文章图片

  • Sobel算子可以有效的提取图像边缘,但是对图像中较弱的边缘提取效果较差。因此为了能够有效的提取出较弱的边缘,需要将像素值间的差距增大,因此引入Scharr算子。Scharr算子是对Sobel算子差异性的增强,因此两者之间的在检测图像边缘的原理和使用方式上相同。Scharr算子的边缘检测滤波的尺寸为3×3,因此也有称其为Scharr滤波器。可以通过将滤波器中的权重系数放大来增大像素值间的差异,Scharr算子就是采用的这种思想,其在X方向和Y方向的边缘检测算子
dst = cv2.Scharr(src,ddpeth,dx,dy)
与Sobel算子相同
img = cv2.imread('F:/images/3.jpg',cv2.IMREAD_GRAYSCALE) scharr_x = cv2.Scharr(img,cv2.CV_64F,1,0) scharr_y = cv2.Scharr(img,cv2.CV_64F,0,1) scharr_x = cv2.convertScaleAbs(scharr_x) scharr_y = cv2.convertScaleAbs(scharr_y) res = cv2.addWeighted(scharr_x,0.5,scharr_y,0.5,0) plt.subplot(121),plt.imshow(res),plt.title('shcarr') plt.subplot(122),plt.imshow(res1),plt.title('sobel') plt.show()

4.laplacian算子
深度学习|opencv基本操作
文章图片

深度学习|opencv基本操作
文章图片

img = cv2.imread('F:/images/3.jpg',cv2.IMREAD_GRAYSCALE) sobel_x = cv2.Sobel(img,cv2.CV_64F,1,0,ksize = 3) sobel_y = cv2.Sobel(img,cv2.CV_64F,0,1,ksize = 3) sobel_x = cv2.convertScaleAbs(sobel_x) sobel_y = cv2.convertScaleAbs(sobel_y) sobel_xy = cv2.addWeighted(sobel_x,0.5,sobel_y,0.5,0)scharr_x = cv2.Scharr(img,cv2.CV_64F,1,0) scharr_y = cv2.Scharr(img,cv2.CV_64F,0,1) scharr_x = cv2.convertScaleAbs(scharr_x) scharr_y = cv2.convertScaleAbs(scharr_y) scharr_xy = cv2.addWeighted(scharr_x,0.5,scharr_y,0.5,0)laplacian = cv2.Laplacian(img,cv2.CV_64F) laplacian = cv2.convertScaleAbs(laplacian) plt.subplot(131),plt.imshow(sobel_xy),plt.title('SOBEL') plt.subplot(132),plt.imshow(scharr_xy),plt.title('SCHARR') plt.subplot(133),plt.imshow(laplacian),plt.title('LAPLACIAN') plt.show()

我们发现Laplacian算子进行边缘检测并没有像Sobel或Prewitt那样的平滑过程,所以它会对噪声产生较大的响应,并且无法分别得到水平方向、垂直方向或者其他固定方向的的边缘。但是它只有一个卷积核,所以计算成本会更低。
# 先对图像进行高斯滤波处理再进行Laplacian算子边缘检测 img = cv2.imread('F:/images/1.jpg') img = cv2.GaussianBlur(img,(3,3),1) laplacian = cv2.Laplacian(img,cv2.CV_64F) laplacian = cv2.convertScaleAbs(laplacian)# 将laplacian算子得出的的结果和原图像进行叠加,来实现锐化效果res = cv2.addWeighted(img,0.5,laplacian,0.5,0) plt.subplot(131),plt.imshow(img),plt.title('original') plt.subplot(132),plt.imshow(laplacian),plt.title('laplacian') plt.subplot(133),plt.imshow(res),plt.title('result') plt.show()

5.图像金字塔与轮廓检测 1.库的导入
import cv2 import numpy as np import matplotlib.pyplot as plt

2 .图像金字塔
深度学习|opencv基本操作
文章图片

1.高斯图像金字塔 深度学习|opencv基本操作
文章图片

<1> 对图像G_i进行高斯内核卷积,进行高斯模糊;
<2> 将所有偶数行和列去除。
得到的图像即为G_i+1的图像,显而易见,结果图像只有原图的四分之一。通过对输入图像G_i(原始图像)不停迭代以上步骤就会得到整个金字塔。同时我们也可以看到,向下取样会逐渐丢失图像的信息。以上就是对图像的向下取样操作,即缩小图像。
  • 对图像的向上取样,即放大图像
1.向下采样(缩小) 深度学习|opencv基本操作
文章图片

对图像进行高斯核卷积操作
img = cv2.imread('F:/images/3.jpg') img = cv2.pyrDown(img) cv_show('result',img) img.shape

2.向上采样(放大)
img = cv2.pyrUp(img) cv_show('result',img) img.shape

2.拉普拉斯图像金字塔 深度学习|opencv基本操作
文章图片

原图像 - 原图像先向上采样,再向下采样的结果
深度学习|opencv基本操作
文章图片

作用利用拉普拉斯图像金字塔对向下采样后的图像进行完美还原,从而实现反卷积的过程
OpenCV中使用pyrDown/pyrUp和resize都可以达到缩放图像的目的,区别在于前者是基于高斯模糊然后降采样,而后者是直接通过插值的方法
图像金字塔内容详情见:
1.csdn链接
2.csdn链接
看了哔哩哔哩链接花了一部分时间整理一下opencv入门的基本操作,仅供参考

    推荐阅读