实验一 图像预处理
计算机视觉OpenCV基础实验合辑(实验1234+扩展)
资源下载地址: https://download.csdn.net/download/weixin_53403301
合辑:(加在下载地址后面)
/87113581
讲义(包括理论、图例、PPT、实验、代码、手册):(加在下载地址后面)
/87113633
matplotlib中载入中文字体
plt.rcParams['font.sans-serif'] = ['SimHei'] # 载入字体
实验目的:
1、 学习并初步掌握OpenCV使用方法;
2、 掌握图像预处理技术编程实现。
实验内容:
1、Opencv安装及配置;Opencv基本操作。
具体包括:图像读取、存盘、显示;图像上图形操作;图像算术操作。
内容清单及所使用的函数:
- 图像IO操作的API:
cv.imread(): 读取图像
cv.imshow():显示图像
cv.imwrite(): 保存图像
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 以灰度图的形式读取图像
img = cv.imread('./image/cat.jpeg',0)
# opencv中显示
cv.imshow('image',img)
cv.waitKey(0)
# 3 保存图像
cv.imwrite('./image/cat2.jpeg',img)
# matplotlib中展示
img = cv.imread('./image/cat2.jpeg')
plt.imshow(img[:,:,::-1])
plt.title('匹配结果'), plt.xticks([]), plt.yticks([])
plt.show()
k = cv.waitKey(0)
- 在图像上绘制几何图像
cv.line(): 绘制直线
cv.circle(): 绘制圆形
cv.rectangle(): 绘制矩形
cv.putText(): 在图像上添加文字
font
# -*- coding: utf-8 -*-
import numpy as np
import cv2 as cv
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)
# 3 图像展示
plt.imshow(img[:,:,::-1])
plt.title('匹配结果'), plt.xticks([]), plt.yticks([])
plt.show()
- 直接使用行列索引获取图像中的像素并进行修改
- 图像的属性
img.shape
img.size
img.dtype
-
拆分通道:cv.split()
通道合并:cv.merge() -
色彩空间的改变
import numpy as np
import cv2 as cv
img = cv.imread('./image/cat.jpeg')
# 获取某个像素点的值
px = img[100,100]
print('像素值',px)
# 仅获取蓝色通道的强度值
blue = img[100,100,0]
# 修改某个位置的像素值
img[100,100] = [255,255,255]
print('修改后像素值',px,'蓝色强度值',blue)
# 形状
xz = img.shape
# 大小
dx = img.size
# 类型
lx = img.dtype
print('形状',xz,'大小',dx,'类型',lx)
# 通道拆分
b,g,r = cv.split(img)
print('拆分')
print(b,g,r)
# 通道合并
img2 = cv.merge((b,g,r))
print('合并')
print(img2)
# 色彩空间的改变
img3 = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
cv.imshow('image',img3)
cv.waitKey(0)
img4 = cv.cvtColor(img,cv.COLOR_BGR2HSV)
cv.imshow('image',img4)
cv.waitKey(0)
7. 图像加法:将两幅图像加载一起
cv.add()
- 图像的混合:将两幅图像按照不同的比例进行混合
- 减、乘、除法
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 1 读取图像
#注意文件名,两个图像的格式、分辨率大小、长宽比需要相同
img1 = cv.imread('./image/1.jpg')
img2 = cv.imread('./image/2.jpg')
# 2 加法操作
img3 = cv.add(img1,img2) # cv中的加法
img4 = img1+img2 # 直接相加
print(img3,img4)
# 3 图像显示
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img3[:,:,::-1])
axes[0].set_title('cv中的加法')
axes[1].imshow(img4[:,:,::-1])
axes[1].set_title('直接相加')
plt.show()
# 图像混合
img5 = cv.addWeighted(img1,0.7,img2,0.3,0)
# 3 图像显示
plt.figure(figsize=(8,8))
plt.imshow(img5[:,:,::-1])
plt.show()
img6 = img1-img2 # 直接相减
img7 = img2-img1 # 反向相减
# 3 图像显示
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img6[:,:,::-1])
axes[0].set_title('1-2')
axes[1].imshow(img7[:,:,::-1])
axes[1].set_title('2-1')
plt.show()
img8 = img1*img2 # 直接相乘
img9 = img2*img1 # 反向相乘
# 3 图像显示
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img8[:,:,::-1])
axes[0].set_title('12')
axes[1].imshow(img9[:,:,::-1])
axes[1].set_title('21')
plt.show()
img10 = img1/img2 # 直接相除
img11 = img2/img1 # 反向相除
# 3 图像显示
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img10[:,:,::-1])
axes[0].set_title('12')
axes[1].imshow(img11[:,:,::-1])
axes[1].set_title('21')
plt.show()
2、图像预处理:
(1)几何变换:图像缩放、图像平移、图像旋转、仿射变换、透射变换;
-
图像缩放:对图像进行放大或缩小
cv.resize() -
图像平移:
指定平移矩阵后,调用cv.warpAffine()平移图像 -
图像旋转:
调用cv.getRotationMatrix2D获取旋转矩阵,然后调用cv.warpAffine()进行旋转 -
仿射变换:
调用cv.getAffineTransform将创建变换矩阵,最后该矩阵将传递给cv.warpAffine()进行变换 -
透射变换:
通过函数cv.getPerspectiveTransform()找到变换矩阵,将cv.warpPerspective()进行投射变换 -
金字塔
图像金字塔是图像多尺度表达的一种,使用的API:
cv.pyrUp(): 向上采样
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 1. 读取图片
img1 = cv.imread("./image/dog.jpeg")
# 2.图像缩放
# 2.1 绝对尺寸
rows,cols = img1.shape[:2]
res = cv.resize(img1,(2*cols,2*rows),interpolation=cv.INTER_CUBIC)
# 2.2 相对尺寸
res1 = cv.resize(img1,None,fx=0.5,fy=0.5)
# 3 图像显示
# 3.1 使用opencv显示图像(不推荐)
#
# 3.2 使用matplotlib显示图像
fig,axes=plt.subplots(nrows=1,ncols=3,figsize=(10,8),dpi=100)
axes[0].imshow(res[:,:,::-1])
axes[0].set_title("绝对尺度(放大)")
axes[1].imshow(img1[:,:,::-1])
axes[1].set_title("原图")
axes[2].imshow(res1[:,:,::-1])
axes[2].set_title("相对尺度(缩小)")
plt.show()
img2 = cv.imread("./image/image2.jpg")
# 2. 图像平移
rows,cols = img2.shape[:2]
M = M = np.float32([[1,0,100],[0,1,50]])# 平移矩阵
dst = cv.warpAffine(img2,M,(cols,rows))
# 3. 图像显示
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img2[:,:,::-1])
axes[0].set_title("原图")
axes[1].imshow(dst[:,:,::-1])
axes[1].set_title("平移后结果")
plt.show()
# 2 图像旋转
rows,cols = img2.shape[:2]
# 2.1 生成旋转矩阵
M = cv.getRotationMatrix2D((cols/2,rows/2),90,1)
# 2.2 进行旋转变换
dst = cv.warpAffine(img2,M,(cols,rows))
# 3 图像展示
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img2[:,:,::-1])
axes[0].set_title("原图")
axes[1].imshow(dst[:,:,::-1])
axes[1].set_title("旋转后结果")
plt.show()
# 重载
img = cv.imread("./image/image2.jpg")
# 2 仿射变换
rows,cols = img.shape[:2]
# 2.1 创建变换矩阵
pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[100,100],[200,50],[100,250]])
M = cv.getAffineTransform(pts1,pts2)
# 2.2 完成仿射变换
dst = cv.warpAffine(img,M,(cols,rows))
# 3 图像显示
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img[:,:,::-1])
axes[0].set_title("原图")
axes[1].imshow(dst[:,:,::-1])
axes[1].set_title("仿射后结果")
plt.show()
# 2 透射变换
rows,cols = img.shape[:2]
# 2.1 创建变换矩阵
pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[100,145],[300,100],[80,290],[310,300]])
T = cv.getPerspectiveTransform(pts1,pts2)
# 2.2 进行变换
dst = cv.warpPerspective(img,T,(cols,rows))
# 3 图像显示
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img[:,:,::-1])
axes[0].set_title("原图")
axes[1].imshow(dst[:,:,::-1])
axes[1].set_title("透射后结果")
plt.show()
# 2 进行图像采样
up_img = cv.pyrUp(img) # 上采样操作
img_1 = cv.pyrDown(img) # 下采样操作
# 3 图像显示
cv.imshow('enlarge', up_img)
cv.imshow('original', img)
cv.imshow('shrink', img_1)
cv.waitKey(0)
cv.destroyAllWindows()
(2)空间域滤波:均值滤波、高斯滤波、中值滤波;
- 图像噪声
椒盐噪声:图像中随机出现的白点或者黑点
高斯噪声:噪声的概率密度分布是正态分布
- 图像平滑
均值滤波:算法简单,计算速度快,在去噪的同时去除了很多细节部分,将图像变得模糊
cv.blur()
高斯滤波: 去除高斯噪声
中值滤波: 去除椒盐噪声
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 1 图像读取
img = cv.imread('./image/sp.png')
# 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()
# 1 图像读取
img2 = cv.imread('./image/ga.png')
# 2 高斯滤波
blur = cv.GaussianBlur(img2,(3,3),1)
# 3 图像显示
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img2[:,:,::-1]),plt.title('原图')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(blur[:,:,::-1]),plt.title('高斯滤波后结果')
plt.xticks([]), plt.yticks([])
plt.show()
# 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()
(3)直方图修正:直方图均衡、直方图自适应均衡。
-
灰度直方图:
cv.calcHist(images,channels,mask,histSize,ranges [,hist [,accumulate]]) -
掩膜
创建蒙版,透过mask进行传递,可获取感兴趣区域的直方图 -
直方图均衡化:增强图像对比度的一种方法
cv.equalizeHist(): 输入是灰度图像,输出是直方图均衡图像 -
自适应的直方图均衡
将整幅图像分成很多小块,然后再对每一个小块分别进行直方图均衡化,最后进行拼接
clahe = cv.createCLAHE(clipLimit, tileGridSize)
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
# 1 直接以灰度图的方式读入
img = cv.imread('./image/cat.jpeg',0)
# 2 统计灰度图
histr = cv.calcHist([img],[0],None,[256],[0,256])
# 3 绘制灰度图
plt.figure(figsize=(10,6),dpi=100)
plt.plot(histr)
plt.grid()
plt.show()
# 2. 创建蒙版
mask = np.zeros(img.shape[:2], np.uint8)
mask[400:650, 200:500] = 255
# 3.掩模
masked_img = cv.bitwise_and(img,img,mask = mask)
# 4. 统计掩膜后图像的灰度图
mask_histr = cv.calcHist([img],[0],mask,[256],[1,256])
# 5. 图像展示
fig,axes=plt.subplots(nrows=2,ncols=2,figsize=(10,8))
axes[0,0].imshow(img,cmap=plt.cm.gray)
axes[0,0].set_title("原图")
axes[0,1].imshow(mask,cmap=plt.cm.gray)
axes[0,1].set_title("蒙版数据")
axes[1,0].imshow(masked_img,cmap=plt.cm.gray)
axes[1,0].set_title("掩膜后数据")
axes[1,1].plot(mask_histr)
axes[1,1].grid()
axes[1,1].set_title("灰度直方图")
plt.show()
# 2. 创建一个自适应均衡化的对象,并应用于图像
clahe = cv.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
cl1 = clahe.apply(img)
# 3. 图像展示
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img,cmap=plt.cm.gray)
axes[0].set_title("原图")
axes[1].imshow(cl1,cmap=plt.cm.gray)
axes[1].set_title("自适应均衡化后的结果")
plt.show()
# 2. 均衡化处理
dst = cv.equalizeHist(img)
# 3. 图像展示
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img,cmap=plt.cm.gray)
axes[0].set_title("原图")
axes[1].imshow(dst,cmap=plt.cm.gray)
axes[1].set_title("均衡化后的结果")
plt.show()
实验收获:
了解到了关于图像处理的基本操作,并在OpenCV中执行,也学习到了在MATLAB中,图像RGB读取顺序的不同,并学会了通过OpenCV和MATLAB显示图像的方法。