1. ○ 图像基础知识
  2. ■ 数字图像
  3. ● 概念与起源
  4. ● 常见的成像方式:伽马射线成像、X射线成像、红外线成像、可见光成像等
  5. ■ 图像的属性
  6. ● 格式、尺寸、分辨率、通道、图像直方图、色彩空间
  7. ○ 图像处理
  8. ■ 绘图&添加文字
  9. ■ 图像几何变换
  10. ■ 图像滤波与增强
  11. ● 线性滤波、非线性滤波
  12. ● 图像锐化
  13. ● 直方图均衡化
  14. ● gamma变化
  15. ■ 形态学变
  16. ● 腐蚀、膨胀
  17. ● 开运算(腐蚀后膨胀)、闭运算(膨胀后腐蚀)
  18. ● 形态学梯度
  19. ● 顶帽、黑帽
  20. ○ 图像分割
  21. ■ 阈值分割
  22. ■ 边缘检测
  23. ■ 连通域分析
  24. ■ 图像轮廓
  25. ■ 区域生长
  26. ■ 分水岭算法
  27. ○ 图像特征与目标检测
  28. ■ 图像特征的理解
  29. ■ 形状特征、纹理特征
  30. ■ 模板匹配
  31. ■ 人脸检测&行人检测
  32. ○ 运动目标识别
  33. ■ 帧差法
  34. ■ 光流法
  35. ■ 背景减除法

一、图像基础知识

1.1 数字图像

1.1.1概念与起源

数字图像又被称为数码图像或数位图像,可以理解为用数字对图像进行编码,将其转化为计算机能理解、传输、表示、操作的格式。1921年最早被用在报社。

1.1.2 常见的成像方式

image.png

1.2 图像的属性

  1. import cv2
  2. data = cv2.imread("../test.png", 0)
  3. # imread函数的参数1是待读取图像的(相对或绝对)路径;
  4. # imread函数的参数2是读取方式,0表示读取为灰度图,1表示按原图读取但是忽略alpha通道,-1表示按原图读取保留alpha
  5. print(data.shape) # 返回图像的:高、宽、通道数
  6. cv2.imshow("ori-data", data)
  7. # imshow函数的参数1是图像显示窗口名称;参数2是需要显示图像的变量名称
  8. cv2.waitKey(0) #waitKey函数控制着imshow的持续时间(单位为ms),当该函数传入参数0时表示无限制显示
  9. cv2.destroyAllWindows() # 用于释放显示占用的相关内存。若不调用该函数,程序运行也能成功,只不过需要等程序结束后再释放相关内存。

image.png
注意:OpenCV的函数常用小驼峰命名法。即首个单词的首字母小写,此后的每个单词的首字母都为大写。

1.2.1 图像格式

  • BMP:Windows下的标准位图格式,未经过压缩,占用内存较大。(如工业相机成像)
  • JPEG:具有较大压缩比(2:1~40:1),使用广泛。
  • GIF:可静可动、支持透明背景;内存占用小,但是色域不广,只支持256种颜色。(如表情包)
  • PNG:与JPEG类似,压缩比高于GIF,支持透明图层(通过alpha通道跳接图像的透明度)。
  • TIFF:图像格式复杂,存储信息多,在mac中广泛使用(利用原稿的复制)。(如卫星地图数据标注)

    1.2.2 图像尺寸

    图像尺寸的长宽都是以像素为单位。像素可以理解为一个点,也可以理解为一个小区域的颜色值。
    像素取值在[0,255]之间 。其中灰度图中0表示黑色、255表示白色;彩色图像用红绿蓝三通道的二维矩阵来表示,0表示相应的基色,255表示相应的基色在改像素中取得最大值。
    注意:

    • uint8:无符号的整型,范围是2^8=256(0~256),因此一般用于表示像素取值。
    • int8:有符号整型,范围是2^8=256(-127,127)。

      1.2.3 分辨率和通道

  • 分辨率:单位长度中所表达或截取的像素数目。

    • 每英寸图像内的像素点数,单位是像素每英寸(PPI:Pixels Per Inch)。图像分辨率越高,像素点密度越高,图像越清晰。
  • 通道数:图像的位深,指描述图像中每个pixel数值所占的二进制位数。
    • 位深度越大则图像能表示的颜色就越多,色彩越丰富。
    • 8位:单通道-灰度图,灰度值范围为2^8=256
    • 24位:三通道3*8=24
    • 32位:三通道加透明alpha通道,alpha通道中0是全透明,255是不透明
  • 练习1:利用cvtColor函数进行图像的通道降维或升维
    • 通道降维(彩色图转灰度图)公式:Gray = B0.299 + G0.587 + R*0.114
    • 通道升维(灰度图转彩色图)公式:B = G = R = Gray = 0; A = 0 ```python import cv2 data = cv2.imread(“../test.png”) print(data.shape) # (768, 1024, 3) cv2.imshow(“ori-data”, data) # 彩色图像 cv2.waitKey(0)

data_gray = cv2.cvtColor(data, cv2.COLOR_BGR2GRAY) print(data_gray.shape) # (768, 1024) cv2.imshow(“gray-data”, data_gray) # 灰度图 cv2.waitKey(0)

data_bgr = cv2.cvtColor(data_gray, cv2.COLOR_GRAY2BGR) print(data_bgr.shape) # (768, 1024, 3) cv2.imshow(“bgr-data”, data_bgr) # 彩色图像,但是效果与转化前的灰度图一样。 cv2.waitKey(0) cv2.destroyAllWindows()

  1. 效果图: ![image.png](https://cdn.nlark.com/yuque/0/2022/png/12845815/1652013318096-4661bcbc-9960-4a76-9af9-e4d3899b6658.png#clientId=uac43b5ea-c574-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=85&id=u2c828e54&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1214&originWidth=1563&originalType=binary&ratio=1&rotation=0&showTitle=false&size=71978&status=done&style=none&taskId=u56092f16-04e4-4333-b181-9af6eb12894&title=&width=109)![image.png](https://cdn.nlark.com/yuque/0/2022/png/12845815/1652013328680-43392b4f-a091-4c7b-8977-4d2f85d4a9b6.png#clientId=uac43b5ea-c574-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=88&id=u8533868d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1214&originWidth=1563&originalType=binary&ratio=1&rotation=0&showTitle=false&size=74472&status=done&style=none&taskId=u2ce73219-e257-412c-9f56-8930bcbfa98&title=&width=113)![image.png](https://cdn.nlark.com/yuque/0/2022/png/12845815/1652013338702-bcb8b3de-a71a-4ddc-8bb0-5f3a40294f45.png#clientId=uac43b5ea-c574-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=85&id=u473814f5&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1214&originWidth=1563&originalType=binary&ratio=1&rotation=0&showTitle=false&size=68097&status=done&style=none&taskId=udc541374-d365-4ae4-9dee-02810016168&title=&width=110)
  2. - 练习2:进行图像的通道顺序转化(即RGB与BGR之间的转化)
  3. - 目的:解决OpenCV与其他包(如matplotlib)读取的通道方式不一样
  4. - 解决方式:OpenCV自带**cvtColor函数**、或者numpy
  5. ```python
  6. import cv2
  7. import matplotlib.pyplot as plt
  8. data = cv2.imread("../test.png")
  9. cv2.imshow("ori-data", data)
  10. cv2.waitKey(0)
  11. data_cv = cv2.cvtColor(data, cv2.COLOR_BGR2RGB)
  12. data_gray = cv2.cvtColor(data, cv2.COLOR_BGR2GRAY) # 转为灰度图,但是在plt中是非灰度的
  13. data_np = data[:, :, ::-1] # numpy自带的数据通道转换
  14. cv2.imshow("rgb-data", data_cv)
  15. cv2.waitKey(0)
  16. plt.subplot(2,2,1)
  17. plt.imshow(data)
  18. plt.subplot(2,2,2)
  19. plt.imshow(data_cv)
  20. plt.subplot(2,2,3)
  21. plt.imshow(data_np)
  22. plt.subplot(2,2,4)
  23. plt.imshow(data_gray) # 单通道灰度图再plt中显示为有颜色(黄紫)的图像
  24. plt.show()
  25. cv2.destroyAllWindows()
  • 效果图:image.pngimage.pngimage.png
  • Note:练习2中用matplotlib进行多图像展示,这里简单说一下它的使用语法。
    • plt.subplot(1,2,1)表示新建一个1行2列的画布,本次的图像在第一个位置上显示。
    • 再结合plt.show进行显示;
    • 如果需要保存图像的话需要用到plt.savefig(保存的路径 +图像名称),保存操作需要在show之前做完。
      • 练习3:图像通道的合并与分离
  • 目的:如果想针对图像中某类特定颜色的对象进行处理,就可以先通道将不同的颜色分离出来;也可以是对图像添加彩色滤镜(针对某一图层*比例系数)。
  • 解决方式:OpenCV自带split函数与merge函数 ```python import cv2 data = cv2.imread(“../task1.jpg”) b,g,r = cv2.split(data) cv2.imshow(“b”, b) # 蓝色通道 cv2.imshow(“g”, g) # 绿色通道 cv2.imshow(“r”, r) # 红色通道 cv2.waitKey(0)

data_merge = cv2.merge([b, g, r*0]) # 将红色通道置为0之后的效果 cv2.imshow(“merge-data”, data_merge) cv2.waitKey(0) cv2.destroyAllWindows()

  1. 效果图:![image.png](https://cdn.nlark.com/yuque/0/2022/png/12845815/1652015787966-40f466a3-06d0-4907-9f0b-8a74fb3d2974.png#clientId=uac43b5ea-c574-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=145&id=u529c4ff5&margin=%5Bobject%20Object%5D&name=image.png&originHeight=361&originWidth=273&originalType=binary&ratio=1&rotation=0&showTitle=false&size=70348&status=done&style=none&taskId=u0dcfd828-fd3d-4b35-b62d-2f23e16760f&title=&width=110)![image.png](https://cdn.nlark.com/yuque/0/2022/png/12845815/1652015634309-bc0f3df0-2fe7-4931-ab6b-ecd2b5e7424d.png#clientId=uac43b5ea-c574-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=145&id=u46977b5d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=570&originWidth=392&originalType=binary&ratio=1&rotation=0&showTitle=false&size=84717&status=done&style=none&taskId=u2e59c622-f11b-4a1c-a0f0-1281fae3412&title=&width=100)![image.png](https://cdn.nlark.com/yuque/0/2022/png/12845815/1652015642888-f693e9ba-8eab-48ca-bab1-0c43edca5bc2.png#clientId=uac43b5ea-c574-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=145&id=ua8af21a0&margin=%5Bobject%20Object%5D&name=image.png&originHeight=570&originWidth=392&originalType=binary&ratio=1&rotation=0&showTitle=false&size=92754&status=done&style=none&taskId=ubae90235-4354-4689-98bb-c3c176ce1b8&title=&width=100)![image.png](https://cdn.nlark.com/yuque/0/2022/png/12845815/1652015744390-7b7daee6-c320-4c61-9c6f-1998c0b7425f.png#clientId=uac43b5ea-c574-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=145&id=ud3b7852f&margin=%5Bobject%20Object%5D&name=image.png&originHeight=554&originWidth=382&originalType=binary&ratio=1&rotation=0&showTitle=false&size=78245&status=done&style=none&taskId=u8f033b1e-a572-4eac-a846-50bbcd4c79f&title=&width=100)![image.png](https://cdn.nlark.com/yuque/0/2022/png/12845815/1652015758217-2add2d55-dd28-43a2-a040-31db6b1790a5.png#clientId=uac43b5ea-c574-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=145&id=ue79dcad8&margin=%5Bobject%20Object%5D&name=image.png&originHeight=550&originWidth=376&originalType=binary&ratio=1&rotation=0&showTitle=false&size=112914&status=done&style=none&taskId=u4fd23c21-7d0d-436e-a22f-df7f59aa7d0&title=&width=99)
  2. <a name="cMAiN"></a>
  3. ### 1.2.4 图像直方图
  4. - **直方图**:统计图像中每个像素强度出现的次数或频率。可用于图像的二值分割或者均衡化。
  5. - 灰度图的直方图实现:
  6. - **cv2.calcHist函数**介绍:参数1是需要计算直方图的图像(支持彩色图像和灰度图),但是需要在图像外面加一个list升维;参数2是通道索引;参数3是函数传入的mask,无mask需要传入none;参数4表示直方图的份数(bins);参数5表示需要统计的像素值范围。
  7. ```python
  8. import cv2
  9. import matplotlib.pyplot as plt
  10. data = cv2.imread("../task1.png")
  11. data_gray = cv2.cvtColor(data, cv2.COLOR_BGR2GRAY)
  12. plt.imshow(data_gray, cmap=plt.cm.gray)
  13. hist = cv2.calcHist([data_gray], [0], None, [256], [0,256])
  14. # 对data_gray图像的第0通道计算【0,256】像素值的直方图,并将结果分为256份进行显示。计算过程中未使用mask
  15. plt.figure()
  16. plt.title("grayscale histogram")
  17. plt.xlabel("bins")
  18. plt.ylabel("the number of pixels")
  19. plt.plot(hist)
  20. plt.xlim([-1, 256])
  21. plt.show()

效果图:image.pngimage.png

  • 彩色图像的直方图实现:需要将彩色图下个传入cv2.calcHist函数中,再修改传入的通道数索引即可

    1.2.5 色彩空间

  • 色彩空间分为:RGB空间、HSV空间、HSI空间、CMYK空间

    • ① 在RGB空间中,我们会使用一个三维向量表示一个像素的颜色。(最常用)
      • 该空间可以用一个正方体表示:正方体的六个顶点分别为——黑白、红绿蓝、黄(红+绿)、青(蓝+绿)、紫(红+蓝)。其中黑白顶点的这条对角线被称为灰度线,上面所有分量的值是一样的。
      • image.png
    • ② HSV:根据色调、饱和度和明度表示图像。
      • 该空间可以用一个倒放的圆锥体表示。其中:
        • h(hue)表示色调、色彩。其中0度表示红色、120度表示绿色、240度表示蓝色;
        • s(saturation)表示饱和度,取值范围为0~100%,值越大,颜色越饱和。可以理解为圆的半径;
        • v(value)明暗,数值越高,越明亮。0(暗)~100%(明)。可以理解为圆锥的高。

image.png

  1. import cv2
  2. import matplotlib.pyplot as plt
  3. data = cv2.imread("../test.png")
  4. hsv = cv2.cvtColor(data, cv2.COLOR_BGR2HSV)
  5. cv2.imshow("hsv", hsv)
  6. cv2.waitKey(0)
  7. cv2.destroyAllWindws()
  1. - 效果图(左边是原图,右边是转换后的效果图)![image.png](https://cdn.nlark.com/yuque/0/2022/png/12845815/1652015787966-40f466a3-06d0-4907-9f0b-8a74fb3d2974.png#clientId=uac43b5ea-c574-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=116&id=ixJSB&margin=%5Bobject%20Object%5D&name=image.png&originHeight=361&originWidth=273&originalType=binary&ratio=1&rotation=0&showTitle=false&size=70348&status=done&style=none&taskId=u0dcfd828-fd3d-4b35-b62d-2f23e16760f&title=&width=88)![image.png](https://cdn.nlark.com/yuque/0/2022/png/12845815/1652941181305-d7239389-390c-48d6-aac4-59ca7eb708c0.png#clientId=u7cac5b4a-1e66-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=117&id=ud718c504&margin=%5Bobject%20Object%5D&name=image.png&originHeight=570&originWidth=384&originalType=binary&ratio=1&rotation=0&showTitle=false&size=157577&status=done&style=none&taskId=u44bdf5c6-af76-4e4d-ba22-979e3627134&title=&width=79)
  • ③ HSI:反应人类视觉系统感知彩色的方式,以色调、饱和度和强度来感知颜色。
    • 该空间可以用纺锤体表示。

image.png

  1. - [HSI与HSV之间的区别](https://zhidao.baidu.com/question/155499261.html)为:HSV颜色模型中,色调H用角度度量取值范围为0°~360°,饱和度S取值范围为0%~100%,明度V取值范围为0%(黑)到100%(白)。HSI颜色模型双六棱锥表示中,色调H的角度范围为[0,2π],饱和度S是颜色空间任一点距I轴的距离。
  2. - HSI的优点:
  3. - 可仅对分量i进行处理,结果不改变原图像中的色彩种类;
  4. - 与人感知颜色的结果一一对应
  • ④ CMYK:主要应用于印刷工业、通过青(c)、品(m)、黄(y)三原色油墨的不同网点面积率的叠印来表现丰富的颜色和阶调
    image.png

二、图像处理

2.1 绘图&添加文字(6种)

  1. 直线:cv2.line(图像、起点(x,y)、终点(x,y)、线段颜色、线宽(线宽或者进行填充-1)、直线类型(默认为8型,还有一种AA型可选))
  2. 矩形:cv2.rectangle(图像、左上角坐标(x,y)、右下角坐标(x,y)、线段颜色、线宽(线宽或者进行填充-1)、线段类型)
  3. 圆:cv2.circle(图像、圆心(x,y)、半径、线段颜色、线宽(线宽或者进行填充-1)、线段类型)
  4. 椭圆:cv2.ellipse(图像、椭圆圆心(x,y)、长短轴(长, 短)、旋转角angle、椭圆的起始角度、椭圆的结束角度、线段颜色、线宽(线宽或者进行填充-1)、线段类型)
    • 角度解析:当椭圆的长轴与x轴平行时,认为其旋转角为0;当其长轴与y轴平行时,认为其旋转角为90;角度会从x轴开始顺时针旋转。
  5. 多边形:cv2.polylines(图像、点对(x,y)、isClosed(线段是否闭合)、线段颜色、线宽(线宽或者进行填充-1)、线段类型)
    • isClosed解析:True为将点对的首尾相连,返回一个闭合的形状;False为不需要将首尾相连,可能会返回一个非闭合的折现线段(是否闭合取决于给定线段的收尾坐标是否相等)。
  6. 添加文字:cv2.putText(图像、str文字、文字起点(左下角)、字体、文字大小(缩放比例)、字体颜色、线宽、线段类型)
    • 文字大小(缩放比例),即该字体可能会有一个基础的大小。并不是指字体的像素宽度 ```python import cv2 import numpy as np data = cv2.imread(“../test.png”) cv2.line(data, (0,0), (200, 200), (0,255,255), 5) cv2.rectangle(data, (0,0), (200, 200), (255, 255, 0), 5) cv2.ellipse(data, (100, 100), (100, 50), 0, 50, 180, (255, 0, 0), -1)

      多边形

      pts = np.array([[10,5], [50, 20], [70,30],[20,50],[15, 70]]) cv2.polylines(data, [pts], True, (0,0,255))

      写字

      font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText(data, “test”, (0, 300), font, 4, (255,255,255), cv2.LINE_AA)

cv2.imshow(“plot”, data) cv2.waitKey(0) cv2.destroyAllWindows()

  1. 效果:![image.png](https://cdn.nlark.com/yuque/0/2022/png/12845815/1652946117143-003ffcb3-5893-4fcf-98d5-b3ac0e32b495.png#clientId=u7cac5b4a-1e66-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=166&id=u4044f3ec&margin=%5Bobject%20Object%5D&name=image.png&originHeight=570&originWidth=392&originalType=binary&ratio=1&rotation=0&showTitle=false&size=139670&status=done&style=none&taskId=ueae15af3-1787-43bd-a724-3d6d9a44399&title=&width=114.33334350585938)
  2. <a name="aiwVX"></a>
  3. ## 2.2 图像几何变换
  4. 常见的图像图像几何变换有:缩放、平移、旋转、仿射变换、透视变换。[参考链接1](https://zoucz.com/blog/2019/02/26/67267d60-39cf-11e9-9e7f-cf581750e42a/);[参考链接2](https://blog.csdn.net/mzpmzk/article/details/64919093)
  5. <a name="vjeCP"></a>
  6. ### 2.2.1 缩放(scaling)
  7. - 缩放的相关定义:
  8. - 下采样(subsampled,或降采样downsampled):缩小图像 ;
  9. - 上采样(upsampled):放大图像,以得到更高分辨率的图像。
  10. - 上下采样是用更多或者更少的点去表示一个区域(一个物体)。它是在同样视野中的图像上进行的。
  11. - 相关函数:`cv2.resize(src,dsize=None,fx,fy,interpolation)`
  12. - 参数分别表示:src原图、dsize目标图像大小(与比例因子二选一)、沿x轴的比例因子、y轴的比例因子、interpolation差值方式
  13. - **差值方式介绍**:
  14. 1. 最近邻差值。不需要计算,直接将距离最近的相邻元素的像素值赋给待求像素。
  15. - **公式:**目标矩阵上的像素取值 = 目标矩阵上像素值的位置 * (当前矩阵到目标矩阵的缩放比)
  16. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/12845815/1652947427929-c8c33597-1a6d-4354-94a2-bd0646a52f57.png#clientId=u7cac5b4a-1e66-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=126&id=u60b43179&margin=%5Bobject%20Object%5D&name=image.png&originHeight=229&originWidth=534&originalType=url&ratio=1&rotation=0&showTitle=false&size=56547&status=done&style=none&taskId=u8fef3d54-931e-4a4c-91a9-69f35ef6350&title=&width=293)
  17. - **示例**:将3个像素点的 矩阵差值为4个像素点的矩阵。
  18. - 因此在新矩阵上第0个元素的位置为为0,用第0个像素表示;
  19. - 新矩阵上第一个元素的位置为0.75,用旧矩阵上第一个像素表示;
  20. - 新矩阵上第二个元素为1.5,用用旧矩阵上第二个元素表示;
  21. - 第三个元素为2.25,还是用旧矩阵上的第二个元素表示
  22. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/12845815/1652947427890-59f85c9e-37b8-4f48-a12a-f0f3ce15b9be.png#clientId=u7cac5b4a-1e66-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=249&id=ub0e50726&margin=%5Bobject%20Object%5D&name=image.png&originHeight=530&originWidth=546&originalType=url&ratio=1&rotation=0&showTitle=false&size=78430&status=done&style=none&taskId=u83622390-c72b-4d03-b8d1-c52e4a20bd5&title=&width=257)
  23. 2. 双线性差值。可以理解为在两个方向(水平和垂直)上进行线性差值,将目标点附近的四个像素点的值按比例赋值目标像素。
  24. - 公式:目标矩阵上的元素取值,是先在水平方向上进行两次一阶线性差值,再对差值的结果做一次垂直方向上的差值。
  25. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/12845815/1652947919581-d82ce168-e39d-4be6-ba9b-d96f807016f4.png#clientId=u7cac5b4a-1e66-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=250&id=u55437494&margin=%5Bobject%20Object%5D&name=image.png&originHeight=453&originWidth=686&originalType=url&ratio=1&rotation=0&showTitle=false&size=121110&status=done&style=none&taskId=u3195ec2b-e875-4706-a429-4c533d875b2&title=&width=379)
  26. - 示例:R1和Q21之间的比重*Q11) + (R1和Q11之间的比重*Q21)得到R1的像素值,同理可求得R2的像素值。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/12845815/1652948269455-0bde2e84-e76c-4af8-a55e-a9a499ab6691.png#clientId=u7cac5b4a-1e66-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=137&id=uc525e73a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=451&originWidth=490&originalType=url&ratio=1&rotation=0&showTitle=false&size=83655&status=done&style=none&taskId=ua4e1a585-30d7-4727-85fc-a310795ebc2&title=&width=149)
  27. ```python
  28. import cv2
  29. data = cv2.imread("../test.png")
  30. res1 = cv2.resize(data, None, fx=2, fy=2, interpolation=cv2.INTER_LINEAR)
  31. # 注意,利用fx和fy做图像的缩放时,需要令dsize=None。
  32. h, w = data.shape[:2]
  33. res2 = cv2.resize(data, (int(w*0.8), int(h*0.8)), interpolation=cv2.INTER_AREA)
  34. # 注意,在使用dsize做图像缩放时,需要传入tuple类型的目标图像大小。其中tuple的元素必须是int类型
  35. print(data.shape, res1.shape, res2.shape)
  36. # (339, 243, 3) (678, 486, 3) (271, 194, 3)

2.2.2 平移(shifting)

平移可以理解为分别在x、y轴方向上移动指定长度的偏移量。设(x0, y0)、(x1, y1)分别是平移前/后的坐标点,那么有x1 = x0+△x、y1 = y0+△y。

  • 相关函数:cv2.warpAffine(src, M, dsize, flags,borderMode, borderValue)
    • 参数分别表示:src原图、M变换矩阵、dsize目标图像大小、flags差值方法的组合、borderMode边界像素模式(默认为BORDER_CONSTANT,即用指定常量进行填充)、borderValue 边界填充值;(默认情况下为0)。
      • M作为仿射变换矩阵,一般反映平移或旋转的关系,为InputArray类型的2×3的变换矩阵。
      • flages表示插值方式,默认为flags=cv2.INTER_LINEAR,表示线性插值,此外还有:
        • cv2.INTER_NEAREST(最近邻插值)
        • cv2.INTER_AREA (区域插值)
        • cv2.INTER_CUBIC(三次样条插值)
        • cv2.INTER_LANCZOS4(Lanczos插值)
      • borderMode可选如下:可以看到除了指定常量的方式之外,其他方法都是利用图像本身的像素点进行边界填充。
        image.png ```python import cv2 import numpy as np data = cv2.imread(“../task1.png”)

        手动构造一个平移矩阵,其中x轴移动100个像素,y轴移动25个像素。图像边默认用0填充

        M = np.float32([[1,0,100], [0,1,25]]) h,w = data.shape[:2]

res1 = cv2.warpAffine(data, M, (w, h)) #平移后的图像大小和 原图相同 res2 = cv2.warpAffine(data, M, (w + 100, h + 25)) # 平移后,将图像shape分别增加各方向平移的量,使结果中的原图不被裁剪。 cv2.imshow(“ori”, data) cv2.imshow(“new”, res1) cv2.imshow(“new2”, res2) cv2.waitKey(0) cv2.destroyAllWindows()

  1. 实现效果:![image.png](https://cdn.nlark.com/yuque/0/2022/png/12845815/1652951659629-0072d81f-1dda-48aa-bf9b-898bf54267f2.png#clientId=u7cac5b4a-1e66-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=146&id=ufa819f34&margin=%5Bobject%20Object%5D&name=image.png&originHeight=589&originWidth=1259&originalType=binary&ratio=1&rotation=0&showTitle=false&size=373834&status=done&style=none&taskId=u9610a008-8b5b-4701-af0a-c6dc114e961&title=&width=312)
  2. <a name="GTjXC"></a>
  3. ### 2.2.3 旋转(rotation)
  4. **定义**:以固定点(一般是图像中心)为中心,将图像上所有像素点都统一旋转一定角度。
  5. - 注意:
  6. - ① 图像旋转之后,中间会出现很多空洞点。一般是利用**差值法**对这些点进行处理,避免它们影响画面效果。
  7. - ② 旋转后,在图像宽高之外的区域会被裁剪掉,边缘以外(图像宽高内部)的区域可以用指定颜色填充。
  8. - 公式(在极坐标上进行旋转变换):
  9. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/12845815/1652956706625-57c9da00-630e-4fe0-a8dc-1a0d526690e4.png#clientId=udd236a7f-1da8-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=57&id=ufbff0048&margin=%5Bobject%20Object%5D&name=image.png&originHeight=94&originWidth=551&originalType=url&ratio=1&rotation=0&showTitle=false&size=28475&status=done&style=none&taskId=u828838c0-ab9b-4f5f-bc52-ff769a6b15e&title=&width=332)![image.png](https://cdn.nlark.com/yuque/0/2022/png/12845815/1652956706682-d90bd0e3-1903-4a85-903b-f31197428532.png#clientId=udd236a7f-1da8-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=46&id=u2be68eb0&margin=%5Bobject%20Object%5D&name=image.png&originHeight=102&originWidth=767&originalType=url&ratio=1&rotation=0&showTitle=false&size=51466&status=done&style=none&taskId=u92f7621e-7bd6-47f8-8a69-26ba8ffd8fc&title=&width=343)
  10. - 函数:利用` cv2.getRotationMatrix2D`(图片的旋转中心, 旋转角度, 缩放比例(正为逆时针,负为顺时针))得到一个变换矩阵,再通过仿射变化`warpAffine`函数做图像进行变换操作。
  11. ```python
  12. import cv2
  13. import numpy as np
  14. data = cv2.imread("../task1.png")
  15. h,w = data.shape[:2]
  16. M = cv2.getRotationMatrix2D((float(w/2), float(h/2)), 45, -1)
  17. # 图像旋转中心点支持float类型的数据,坐标也是(X,Y)。
  18. dst = cv2.warpAffine(data, M, (h, w)) # 旋转的目标图像尺寸也是指定宽高,而非高宽(与图像属性shape的顺序不一样)
  19. cv2.imshow("ori", data)
  20. cv2.imshow("new", dst)
  21. cv2.waitKey(0)
  22. cv2.destroyAllWindows()

效果:image.png

2.2.4 翻转(flip)

翻转(也被称为镜像),是指图像围绕翻转轴进行空间180°运动 。翻转后的图像看起来与原图关于对称轴对称。

  • 翻转与旋转的差异:
    • 翻转操作不需要做额外的差值和裁剪,得到的结果图像和原图大小一致。但是物体之前的相对位置可能会发生变化(如左右互换)
    • 旋转过程中需要做差值和padding操作,得到的结果图像大小需要指定。图形的整体都发生了角度变化 ,图像上各元素之间的相对位置未发生改变。
  • 函数:cv2.flip(filename, flipcode) 。flipcode的取值分别有:0 垂直翻转, 1 水平翻转,-1水平垂直翻转。 ```python import cv2 import numpy as np data = cv2.imread(“../task1.png”) h,w = data.shape[:2]

dst = cv2.flip(data, 1) # 沿x=w轴进行的镜面翻转 dst2 = cv2.flip(data, 0) # 沿y=h轴进行的镜面翻转 dst3 = cv2.flip(data, -1) cv2.imshow(“ori”, data) cv2.imshow(“new”, dst) cv2.imshow(“new2”, dst2) cv2.imshow(“new3”, dst3) cv2.waitKey(0) cv2.destroyAllWindows()

利用np进行翻转。

  1. 效果图:![image.png](https://cdn.nlark.com/yuque/0/2022/png/12845815/1652961604375-40adc635-0fba-4a76-8ad3-932b94897ee2.png#clientId=udd236a7f-1da8-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=194&id=u4ecf0024&margin=%5Bobject%20Object%5D&name=image.png&originHeight=1129&originWidth=762&originalType=binary&ratio=1&rotation=0&showTitle=false&size=358744&status=done&style=none&taskId=u077afc34-f3ab-4a89-a6ea-77ed54ee9b3&title=&width=131)
  2. <a name="Fw9mI"></a>
  3. ### 2.2.5 仿射变换()
  4. [仿射变换](https://baike.baidu.com/item/%E4%BB%BF%E5%B0%84%E5%8F%98%E6%8D%A2/4289056?fr=aladdin):又称仿射映射,是指在几何中,一个向量空间进行**一次线性变换**并**接上一个平移**,变换为另一个向量空间。变换前后
  5. - 注意:线性变化前后的图像上线性性保持不变;直线的比例保持不变
  6. - 作用:对图像进行平移、旋转、缩放(等比例缩放)、翻转、斜切等操作。
  7. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/12845815/1652958688705-4cedf23a-d0b2-430f-9874-2683c7a608cf.png#clientId=udd236a7f-1da8-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=210&id=u0160b276&margin=%5Bobject%20Object%5D&name=image.png&originHeight=525&originWidth=744&originalType=binary&ratio=1&rotation=0&showTitle=false&size=298581&status=done&style=none&taskId=u6bb9cc50-f75e-4d45-b2e1-69560dc6d84&title=&width=298)
  8. - 函数:`M = cv2.getAffineTransform(pos1,pos2)`。pos1,pos2分别代表变换前后的3个点的位置(x,y)。通过指定的点实现拉伸和平移、旋转等操作。
  9. ```python
  10. import cv2
  11. import numpy as np
  12. data = cv2.imread("../task1.png")
  13. h,w = data.shape[:2]
  14. # 在二维图像上,两个点确定一条直线,三个点确定一个平面
  15. p1 = np.float32([[50,50], [200,50], [50,200]])
  16. p2 = np.float32([[10,100], [200,50], [100,250]])
  17. M = cv2.getAffineTransform(p1, p2)
  18. dst = cv2.warpAffine(data, M, (w, h))
  19. cv2.imshow("ori", data)
  20. cv2.imshow("new", dst)
  21. cv2.waitKey(0)
  22. cv2.destroyAllWindows()

效果:image.png
应用:用于人脸位姿的矫正

2.2.6 透视变换

透视变换的物理意义:用一个光源照射到你需要处理的图像上,将其投影到另一个平面上的样子。(如皮影戏)

  • 和仿射变换的相同点在于:同样存在平移、缩放、拉伸(拉伸通过斜切实现)等。
  • 和仿射变换的区别在于:透视变化是将一个图像投影到另一个平面上的操作;而前面的平移、旋转、仿射变换等都是在一个图像上的操作。
  • 函数:
    • M = cv2.getPerspectiveTransform(pos1, pos2)。pos1、pos2表示透视变换前、后的4个点对应位置
    • cv2.warpPerspective(src,M,(cols,rows))。src表示原始图像、M表示透视变换矩阵、(rows,cols)表示变换后的图像大小,rows表示行数,cols表示列数 ```python import cv2 import numpy as np data = cv2.imread(“../task1.png”) h,w = data.shape[:2]

p1 = np.float32([[114,82], [288,150], [8,100],[143,182]]) p2 = np.float32([[0,0], [100,0], [0,250], [188,160]]) M = cv2.getPerspectiveTransform(p1, p2) dst = cv2.warpPerspective(data, M, (w, h)) cv2.imshow(“ori”, data) cv2.imshow(“new”, dst) cv2.waitKey(0) cv2.destroyAllWindows() ``` 效果:image.png

2.2.7 图像几何变换应用

图像的几何变换应用 比较广泛,如

  • 图像矫正:用于对人脸图像进行矫正,OCR前处理(文档的矫正)等。
  • 数据增广:用于深度学习中增加数据规模及数据多样性。

待补充知识点:

  • 图像差值方式(除最近邻插值、双线性差值之外)