【笔记】OpenCV图像基本操作

目录

一、图像属性

1.1图像格式

1.2图像尺寸

1.3图像分辨率和通道

1.4图像直方图

1.5图像颜色空间

二、基本操作

2.1 图像读取 cv2.imread()

2.2 图像的显示 cv2.imshow()

2.3 图像的保存 cv2.imwrite()

2.4 用matplotlib显示图像 plt.imshow()

2.5 视频读取 cv2.VideoCapture()

2.6 图像截取、颜色通道提取

2.7边界填充 cv.copyMakeBorder()

 2.8 数值计算 img1+img2  cv2.add(img1,img2)

2.9 图像融合 cv2.addWeighted()

2.10 通道转化 cv2.cvtColor()

2.11 图像阈值 ret, dst = cv2.threshold()

三、图像滤波与增强

3.1 均值滤波 cv2.blur(img, (3, 3))

3.2 方框滤波 cv2.boxFilter(img,-1,(3,3), normalize=True)

3.3 高斯滤波 cv2.GaussianBlur(img, (5, 5), 1)  

3.4 中值滤波 cv2.medianBlur(img, 5)

3.5 双边滤波 cv2.bilateralFilter(img,d,sigmaColor,sigmaSpace)

3.6 直方图 calcHist()

3.7 直方图均衡化 cv2.equalizeHist(img)

3.8 Gamma变换 

四、图像的几何变换

4.1 图像平移  cv2.warpAffine()

4.2 图像缩放 cv2.resize()

4.3 图像旋转 cv2.getRotationMatrix2D()

4.4 放射变换 cv2.getAffineTransform()

4.5 透视变化 cv2.getPerspectiveTransform() / cv2.warpPerspectiveTransform()

五、形态学

5.1 腐蚀操作 cv2.erode()

5.2 膨胀操作 cv2.dilate()

5.3 开运算 cv2.morphologyEx()

5.4 闭运算 cv2.morphologyEx()

5.5 梯度运算

5.6 礼帽与黑帽

5.7 图像梯度

5.7.1 Sobel 算子

5.7.2 Scharr 算子

5.7.3 laplacian 算子

六、边缘检测、提取

6.1 图像金字塔

6.2 Canny 边缘检测算法

6.3 区域生长算法

6.4 图像轮廓 cv2.findContours()

七、傅里叶变换


一、图像属性

1.1图像格式

BMP格式:Windows系统下的标准位图格式,未经过压缩,一般图像文件比较大

JPEG格式:应用最广泛的格式之一,它采用一种特殊的有损压缩算法,达到较大的压缩比(可达到2:1甚至40:1)

GIF格式:可以是一张静止的图片,也可以是动画,支持透明背景图像,适用于多种操作系统,“体型”很小。但是其色域不太广,只支持256种颜色。

PNG格式:与JPG格式类似,压缩比高于GIF,支持图像透明,支持Alpha通道调节图像的透明度。

TIFF:特点是图像格式复杂,存储信息多,在Mac中广泛使用,非常有利于原稿的复制。很多地方将TIFF格式用于印刷。

注:JPEG和JPG区别可参考:https://www.zhihu.com/question/20329498。这里可理解为一个东西。

1.2图像尺寸

图像尺寸的长度和宽度以像素为单位。

像素(pixel):像素是数码影像最基本的单位,每个像素就是一个小点,不同颜色的点聚集起来即成为一幅图片。灰度像素点数值范围在0到255之间,0表示黑,255表示白,其他值表示处于黑白之间;彩色图用红、绿、蓝三通道的二维矩阵来表示。每个数值也是在0~255之间,0表示相应的基色,而255则表示相应的基色在该像素中取得最大值。

1.3图像分辨率和通道

分辨率:单位长度中的像素数目。每英寸图像中的像素点数,单位是像素每英寸(PPI)。图像分辨率越高,像素的点密度越高,图像越清晰。

通道数:图像的位深度,是指描述图像中每个pixel数值所占的二进制数。位深度越大则图像能表示的颜色数就越多,色彩越丰富逼真。

  • 8位:单通道图像,也就是灰度图,灰度值范围2^8=256
  • 24位:三通道3*8=24
  • 32位:三通道加透明度Alpha通道

1.4图像直方图

图像直方图(Image Histogram)是用来表示数字图像中亮度分布的直方图,描绘了图像中每个亮度值的像素数。图像直方图中,横坐标左侧为纯黑、较暗的区域,右侧为较亮、纯白的区域。

图像直方图能表现出图像中的像素强度分布情况,它统计了每一个强度值所具有的像素个数。我们常借助图像直方图来实现图像的二值化。

1.5图像颜色空间

概念:一种彩色模型,用途实在某些标准下用通常可接受的方式对彩色加以说明。

常见颜色空间:RGB HSV HSI CMYK

RGB颜色空间:依据人眼识别的颜色创建,图像中每一个像素都有R,G,B三个颜色分量组成,这三个大小均为【0,255】。通常表示某个颜色的时候,写成一个3维向量的形式,如(105,123,135)。

颜色模型:归一化后,原点(0,0,0)对应黑色,距原点最远的顶点对应白色,坐标为(1,1,1);从黑色到白色的灰度值分布在这两个点的连线上,该虚线称为灰度线;立方体的其余各点对应不同的颜色,红绿蓝等等。

【笔记】OpenCV图像基本操作_第1张图片

HSV颜色空间:根据颜色的直观特性创建的一种颜色空间。这个模型中颜色的参数分别是:色调(H),饱和度(S),明度(V)。

颜色模型:S通道,色彩/色调,代表颜色;S通道,饱和度,取值范围0%~100%,值越大颜色越饱和;V通道,明暗,数值越高越明亮,0%黑到100%白。

【笔记】OpenCV图像基本操作_第2张图片

HSV颜色空间常用数值如下:

【笔记】OpenCV图像基本操作_第3张图片

二、基本操作

2.1 图像读取 cv2.imread()

函数cv2.imread(filename, flags)
参数:
        filepath:读入imge的完整路径,可以绝对路径也可以相对路径
        flags:标志位,{cv2.IMREAD_COLOR,cv2.IMREAD_GRAYSCALE,            cv2.IMREAD_UNCHANGED}
        cv2.IMREAD_COLOR:默认参数,读入一副彩色图片,忽略alpha通道,可用1替代
        cv2.IMREAD_GRAYSCALE:读入灰度图片,可用0替代
        cv2.IMREAD_UNCHANGED:顾名思义,读入完整图片,包括alpha通道,可用-1替代
PS:alpha通道,又称A通道,是一个8位的灰度通道,该通道用256级灰度来记录图像中的透明度复信息,定义透明、不透明和半透明区域,其中黑表示全透明,白表示不透明,灰表示半透明

示例:

img = cv2.imread('D:/wzx/tu1.jpg',-1) 

2.2 图像的显示 cv2.imshow()

函数:cv2.imshow(winname,img)

参数:

        winname:显示图像的窗口的名称,需要引号,例如 ‘img1’

        img:所显示的图像

PS:

1.函数 cv2.imshow() 之后要用 waitKey() 函数设定图像窗口的显示时长,否则不会显示图像窗口。
2.图像窗口将在 waitKey() 函数所设定的时长(毫秒)后自动关闭,waitKey(0) 表示窗口显示时长为无限。
3.可以创建多个不同的显示窗口,每个窗口必须命名不同的 winname
4.可以用 destroyWindow() 函数关闭指定的显示窗口,也可以用 destroyAllWindows() 函数关闭所有的显示窗口。

示例:

img = cv2.imread('D:/wzx/tu1,jpg',-1)
cv2.imshow('img1',img)

cv2.waitKey(0)
cv2.destroyAllWindows()

        按照上述方式创建的窗口无法自由变换大小,对于过小或者过大的图片不适合,所以可通过如下放大创建可变换大小窗口。

函数:cv2.namedWindow(winname, type)

参数:winname:显示图像的窗口的名称,需要引号,例如 ‘img1’

           type:  cv2.WINDOW_NORMAL    # 用户可以改变这个窗口大小
                     cv2.WINDOW_AUTOSIZE    # 窗口大小自动适应图片大小,并且不可手动更改。   
                     cv2.WINDOW_FREERATIO    # 自适应比例
                     cv2.WINDOW_KEEPRATIO    # 保持比例
                     cv2.WINDOW_OPENGL    # 窗口创建的时候会支持OpenGL

示例:

img = cv2.imread('D:/wzx/tu1.jpg',0)
# 创建一个名为“img1”的可变换窗口
cv2.namedWindow('img1',cv2.WINDOW_NORMAL)
# 将图片img显示在窗口“img1”里面
cv2.imshow('img1', img)

cv2.waitKey(0)
cv2.destroyAllWindows()

2.3 图像的保存 cv2.imwrite()

函数:cv2.imwrite(filename, img [, paras])

参数:

        filename:要保存的文件的路径和名称,包括文件扩展名

        img:要保存的 OpenCV 图像,nparray 多维数组

        paras:不同编码格式的参数,可选项

                cv2.CV_IMWRITE_JPEG_QUALITY:设置 .jpeg/.jpg 格式的图片质量,取值为 0-100(默认值 95),数值越大则图片质量越高;
                cv2.CV_IMWRITE_WEBP_QUALITY:设置 .webp 格式的图片质量,取值为 0-100;
                cv2.CV_IMWRITE_PNG_COMPRESSION:设置 .png 格式图片的压缩比,取值为 0-9(默认值 3),数值越大则压缩比越大。

        retval:返回值,保存成功返回 True,否则返回 False。

示例:

# 引号内可以使用绝对路径换文件夹
cv2.imwrite('tu2.jpg',img)

2.4 用matplotlib显示图像 plt.imshow()

函数:matplotlib.pyplot.imshow(img[, cmap])

参数:

  • img:图像数据,nparray 多维数组,对于 openCV(BGR)格式图像要先进行格式转换
  • cmap:颜色图谱(colormap),默认为 RGB(A) 颜色空间
    • gray:灰度显示
    • hsv:hsv 颜色空间

PS:

1.OpenCV 和 matplotlib 中的彩色图像都是 Numpy 多维数组。但 OpenCV 使用 BGR 格式,颜色分量按照 BGR 的次序排列,而 matplotlib 使用 RGB 格式,颜色分量按照红/绿/蓝的次序排序。因此用 plt.imshow() 显示 OpenCV 彩色图像时,先要进行颜色空间转换,将 Numpy 多维数组按照RGB的次序排序。

2.plt.imshow() 可以直接显示 OpenCV 灰度图像,不需要格式转换,但需要使用 cmap=‘gray’ 进行参数设置。例如 plt.imshow(imgGray,'gray')

3.plt.imshow() 可以使用 matplotlib 库中的各种方法绘图,如标题、坐标轴、插值等。

4.图片标题有中文时需要设置字体 fontproperties 参数,如 plt.title('图1',fontproperties="SimHei")

5.subplot 函数可以将多个图片显示在一个窗口下,plt.subplot(121)表示这个窗口有1行2列,该图片位于第1个(图片序列号从左往右,从上往下)

6.PyQt5 也使用 RGB 格式,因此在 PyQt5 中显示 OpenCV 彩色图像时,也要进行颜色空间转换。

示例:

plt.subplot(121),plt.plot(img),plt.title('图1',fontproperties="SimHei")

plt.show()

2.5 视频读取 cv2.VideoCapture()

函数:cv2.VideoCapture()

参数:

        0:打开笔记本内置摄像头

        filename:打开路径下的视频

函数:ret, frame = vc.read()

参数:

        vc.read()按帧读取视频,ret,frame是获cap.read()方法的两个返回值。其中ret是布尔值,如果读取帧是正确的则返回True,如果文件读取到结尾,它的返回值就为False。frame就是每一帧的图像,是个三维矩阵。

函数:vc.release() 

参数:释放摄像头

示例:

import cv2
import numpy as np

capture = cv2.VideoCapture(0)

width,height = capture.get(3),capture.get(4)
capture.set(cv2.CAP_PROP_FRAME_WIDTH, width*2)
capture.set(cv2.CAP_PROP_FRAME_HEIGHT, height*2)

fourcc = cv2.VideoWriter_fourcc(*'MJPG')
outfile = cv2.VideoWriter('Video7.avi',fourcc,25.,(640,480))
while(capture.isOpened()):
    ret,frame = capture.read()
    if ret:
        outfile.write(frame)
        cv2.imshow('frame',frame)
        if cv2.waitKey(1) == ord('q'):
            break
    else:
        break

2.6 图像截取、颜色通道提取

利用Numpy的切片功能

2.7边界填充 cv.copyMakeBorder()

函数:cv2.copyMakeBorder(img,top, bottom, left, right ,borderType)

参数:

        img:需要填充的图像

        top:图像上边界需要填充的像素点

        bottom:图像下边界需要填充的像素点

        left:图像左边界需要填充的像素点

        right:图像右边界需要填充的像素点

        borderType:图像填充的方法,可用方式如下

                BORDER_REPLICATE:复制法,也就是复制最边缘像素

                BORDER_REFLECT:反射法,对感兴趣的图像中的像素在两边进行复制,例如:fedcba|abcdefgh|hgfedcb

                BORDER_REFLECT_101:反射法,也就是以最边缘像素为轴,对称,例如:gfedcb|abcdefgh|gfedcba

                BORDER_WRAP:外包装法,例如:abcdefgh|abcdefgh|abcdefg

                BORDER_CONSTANT:常量法,常数值填充,需要在设置一个value值,已显示填充的颜色

代码示例:

#边界填充
top_size,bottom_size,left_size,right_size = (50,50,50,50)

replicate = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=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.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_WRAP)
constant = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv2.BORDER_CONSTANT, value=0)

#绘制子图
import matplotlib.pyplot as plt
plt.subplot(231), plt.imshow(img, 'gray'), plt.title('ORIGINAL')
plt.subplot(232), plt.imshow(replicate, 'gray'), plt.title('REPLICATE')
plt.subplot(233), plt.imshow(reflect, 'gray'), plt.title('REFLECT')
plt.subplot(234), plt.imshow(reflect101, 'gray'), plt.title('REFLECT_101')
plt.subplot(235), plt.imshow(wrap, 'gray'), plt.title('WRAP')
plt.subplot(236), plt.imshow(constant, 'gray'), plt.title('CONSTANT')

plt.show()

【笔记】OpenCV图像基本操作_第4张图片

 2.8 数值计算 img1+img2  cv2.add(img1,img2)

img1 + img2 :数值相加后%256 

cv2.add(img1,img2):数值相加,若超过255则按255写入

2.9 图像融合 cv2.addWeighted()

函数:cv2.addWeighted(src1, alpha, src2, beta, gamma, dst=None, dtype=None)

参数:

         src1, src2:融合相加的两个图像的 shape 需要一致
         alpha:src1的权重
         beta:src2的权重
         gamma:gamma修正系数,不需要修正设置为0
         dst:可选参数,输出结果保存的变量,默认值为None,如果为非None,输出图像保存到dst对应实参中,其大小和通道数与输入图像相同,图像的深度(即图像像素的位数)由dtype参数或输入图像确认
         dtype:可选参数,输出图像数组的深度,即图像单个像素值的位数(如RGB用三个字节表示,则为24位),选默认值None表示与源图像保持一致。
         返回值:融合相加的结果图像

示例:

res = cv2.addWeighted(img_cat, 0.4, img_dog, 0.6, 0)

plt.imshow(res)

2.10 通道转化 cv2.cvtColor()

函数:cv2.cvtColor(input_image, flag)

参数:input_image:需要转换的图片

           flag:转换的类型,可选类型部分如下

                cv2.COLOR_BGR2GRAY:BGR -> Gray

                cv2.COLOR_BGR2RGB:BGR -> RGB

                cv2.COLOR_BGR2HSV:BGR -> HSV

        Ps:“BGR2GRAY” 中的 “2” 可以巧记为 to 

示例:

# 以 BGR 转 GRAY 为例
imgGray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

2.11 图像阈值 ret, dst = cv2.threshold()

函数:ret, dst = cv2.threshold(src, thresh, maxval, type)

参数:

  • src: 输入图,只能输入单通道图像,通常为灰度图,彩色图需要对每个通道逐一使用

  • dst: 输出图

  • thresh: 阈值

  • maxval: 当像素值超过了阈值(或者小于阈值,根据type是否有_INV来判断),所赋予的值

  • type:二值化操作的类型,包含以下5种类型: 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=cv2.imread('cat.jpg')
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

ret, thresh1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)

plt.subplot(131), plt.imshow(img, 'gray'),plt.title('Original Image')
plt.subplot(132), plt.imshow(thresh1, 'gray'),plt.title('BINARY')
plt.subplot(133), plt.imshow(thresh2, 'gray'),plt.title('BINARY_INV')

plt.show()

【笔记】OpenCV图像基本操作_第5张图片

三、图像滤波与增强

3.1 均值滤波 cv2.blur(img, (3, 3))

        线性滤波,简单的平均卷积,卷积核大小(3,3)可以任意选择,下同

示例:

blur = cv2.blur(img, (3, 3))
cv2.imshow('blur', blur)

3.2 方框滤波 cv2.boxFilter(img,-1,(3,3), normalize=True)

        线性滤波,基本和均值一样,可以通过 normalize 选择是否归一化

示例:

box = cv2.boxFilter(img,-1,(3,3), normalize=True)  
cv2.imshow('box', box)

3.3 高斯滤波 cv2.GaussianBlur(img, (5, 5), 1)  

        线性滤波,高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的

aussian = cv2.GaussianBlur(img, (5, 5), 1)  
cv2.imshow('aussian', aussian)

3.4 中值滤波 cv2.medianBlur(img, 5)

        非线性滤波,相当于用中值代替

median = cv2.medianBlur(img, 5)  
cv2.imshow('median', median)

3.5 双边滤波 cv2.bilateralFilter(img,d,sigmaColor,sigmaSpace)

        双边滤波是结合图像的空间邻近度和像素值相似度的一种折中处理,同时考虑空间与信 息和灰度相似性,达到保变去噪的目的,具有简单、非迭代、局部处理的特点。

        d:像素的邻域直径

        sigmaColor:灰度值相似性高斯函数标准差

        sigmaSpace:空间高斯函数标准差

        关于参数d:过大的滤波器(d>5)执行效率低。 对于实时应用,建议取d=5; 对于需要过滤严重噪声的离线应用,可取d=9; d>0时,由d指定邻域直径; d<=0时,d会自动由sigmaSpace的值确定,且d与sigmaSpace成正比   

        关于2个sigma参数:简单起见,可以令2个sigma的值相等; 如果他们很小(小于10),那么滤波器几乎没有什么效果; 如果他们很大(大于150),那么滤波器的效果会很强,使图像显得非常卡通化

3.6 直方图 calcHist()

函数

cv2.calcHist(images,channels,mask,histSize,ranges)

 参数:

  • images: 原图像图像格式为 uint8 或 float32。当传入函数时应用中括号 [] 括起来,例如[img]
  • channels: 同样用中括号括来它会告函数我们统幅图 像的直方图。如果入图像是灰度图它的值就是 [0]如果是彩色图像 的传入的参数可以是 [0][1][2] 它们分别对应着 BGR。
  • mask: 掩模图像。统整幅图像的直方图就把它为 None。但是如 果你想统图像某一分的直方图的你就制作一个掩模图像并 使用它。
  • histSize:BIN 的数目。也应用中括号括来
  • ranges: 像素值范围常为 [0~256]

Ps:只有参数 mask 不需要中括号

示例:

hist = cv2.calcHist([img],[0],None,[256],[0,256])
plt.hist(img.ravel(),256); 
plt.show()

3.7 直方图均衡化 cv2.equalizeHist(img)

        统计直方图中每个灰度级出现的次数,计算累计归一化直方图,重新计算像素点的像素值。彩色图像均衡化需要对每个通道单独均衡化。

示例:

import cv2
import numpy as np
import matplotlib.pyplot as plt

pic = cv2.imread('./resource/zftjh.jpg',0)

plt.subplot(221),plt.imshow(pic,'gray'),plt.title('原图',fontproperties="SimHei")

plt.subplot(222),plt.hist(pic.ravel(), 256, [0, 256]),plt.title('原图直方图',fontproperties="SimHei")

a = cv2.equalizeHist(pic)
plt.subplot(223),plt.imshow(a,'gray'),plt.title('原图均衡化',fontproperties="SimHei")

plt.subplot(224),plt.hist(a.ravel(), 256, [0, 256]),plt.title('均衡化直方图',fontproperties="SimHei")

plt.show()

【笔记】OpenCV图像基本操作_第6张图片

        局部直方图均衡化:img1 = cv2.createCLAHE(clipLimit=2,tileGridSize=(30,30))

3.8 Gamma变换 

def adjust_gamma(image, gamma=1.0):
    invGamma = 1.0/gamma
    table = []
    for i in range(256):
        table.append(((i / 255.0) ** invGamma) * 255)
    table = np.array(table).astype("uint8")
    print(table)
    return cv2.LUT(image, table)

img_gamma = adjust_gamma(img, 0.8)

四、图像的几何变换

4.1 图像平移  cv2.warpAffine()

函数:cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst

通过变换矩阵 M 对图像 src 进行仿射变换

参数:

        scr:变换操作的输入图像
        M:仿射变换矩阵,2行3列
        dsize: 输出图像的大小,二元元组 (width, height)
        dst:变换操作的输出图像,可选项
        flags:插值方法,整型(int),可选项
        cv2.INTER_LINEAR:线性插值,默认选项
        cv2.INTER_NEAREST:最近邻插值
        cv2.INTER_AREA:区域插值
        cv2.INTER_CUBIC:三次样条插值
        cv2.INTER_LANCZOS4:Lanczos 插值
        borderMode:边界像素方法,整型(int),可选项,默认值为 cv2.BORDER_REFLECT
        borderValue:边界填充值,可选项,默认值为 0(黑色填充)

示例:

import cv2
import numpy as np
img = cv2.imread('img2.png')
# 构造移动矩阵H
# 在x轴方向移动多少距离,在y轴方向移动多少距离
H = np.float32([[1, 0, 50], [0, 1, 25]])
rows, cols = img.shape[:2]
print(img.shape)
print(rows, cols)

# 注意这里rows和cols需要反置,即先列后行
res = cv2.warpAffine(img, H, (2*cols, 2*rows))  
cv2.imshow('origin_picture', img)
cv2.imshow('new_picture', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

4.2 图像缩放 cv2.resize()

方法一:设置缩放比例,来对图像进行放大或缩小

函数:cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_CUBIC)

示例:

res1 = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_CUBIC)
height, width = img.shape[:2]

方法二:直接设置图像的大小,不需要缩放因子

#cv2.INTER_NEAREST(最近邻插值) cv2.INTER_AREA (区域插值) cv2.INTER_CUBIC(三次样条插值) cv2.INTER_LANCZOS4(Lanczos插值)

res2 = cv2.resize(img, (int(0.8*width), int(0.8*height)),interpolation=cv2.INTER_LANCZOS4)
cv2.imshow('origin_picture', img)
#|cv2.imshow('res1', res1)
cv2.imshow('res2', res2)

4.3 图像旋转 cv2.getRotationMatrix2D()

函数:cv2.getRotationMatrix2D(center, angle, scale)

参数:center:旋转中心

          angle:旋转角度,正为逆时针,负为顺时针

          scale:缩放因子

示例:

import cv2
import numpy as np
img=cv2.imread('img2.png',1)
rows,cols=img.shape[:2]
#参数1:旋转中心,参数2:旋转角度,参数3:缩放因子
#参数3正为逆时针,负值为正时针
M=cv2.getRotationMatrix2D((cols/2,rows/2),45,1,)
print(M)
#第三个参数是输出图像的尺寸中心
dst=cv2.warpAffine(img,M,(cols,rows))
#borderValue为填充值
#dst=cv2.warpAffine(img,M,(cols,rows),borderValue=(255,255,255))
while(1):
    cv2.imshow('img', img)
    cv2.imshow('img1',dst)
    #0xFF==27  ESC
    if cv2.waitKey(1)&0xFF==27:
        break
cv2.destroyAllWindows()

4.4 放射变换 cv2.getAffineTransform()

函数:cv2.getAffineTransform(pos1,pos2)

参数:

        pos1:变换前的位置

        pos2:变换后的位置

4.5 透视变化 cv2.getPerspectiveTransform() / cv2.warpPerspectiveTransform()

函数:cv2.getPerspectiveTransform(pos1, pos2)

参数:

        pos1:变换前的4个点对应位置

        pos2:变换后的4个点对应位置

函数:cv2.warpPerspectiveTransform(src, M, (cols,rows))

参数:

        src:原始图像

        M:变换矩阵

        (cols.rows):变换后的图像大小,rows表行数,cols表列数

五、形态学

5.1 腐蚀操作 cv2.erode()

函数:cv2.erode(src,element,anchor,iterations)

参数说明:

        src:原图像

        element:腐蚀操作的内核,默认为(3,3)矩阵,可自定义

        anchor:默认为Point(-1,-1),内核中心点

        iterations:腐蚀次数,默认为1

作用:腐蚀类似于“领域被蚕食”,将图像中白色部分进行缩减细化,其运行结果图比原图的白色区域更小。

示例:

img = cv2.imread('img1.jpg')

kernel = np.ones((3,3),np.uint8) 
erosion = cv2.erode(img,kernel,iterations = 1)

cv2.imshow('erosion', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()

5.2 膨胀操作 cv2.dilate()

函数:cv2.dilate(src, element, anchor, iterations)

参数:同腐蚀操作

作用:膨胀类似于“领域扩张”,将图像中的白色部分进行扩张,其运行结果图比原图的白色区域更大。

img = cv2.imread('img1.jpg')

kernel = np.ones((3,3),np.uint8) 
dilate = cv2.dilate(img,kernel,iterations = 1)

cv2.imshow('dilate', dilate )
cv2.waitKey(0)
cv2.destroyAllWindows()

5.3 开运算 cv2.morphologyEx()

先腐蚀,后膨胀

函数:cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)

cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)

5.4 闭运算 cv2.morphologyEx()

先膨胀,后腐蚀

函数:cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

示例:

img = cv2.imread('dige.png')

kernel = np.ones((5,5),np.uint8) 
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)  #开运算
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel) #闭运算

cv2.imshow('opening', opening)
cv2.waitKey(0)
cv2.destroyAllWindows()

5.5 梯度运算

梯度 = 膨胀 - 腐蚀

函数:cv2.morphologyEx(pie, cv2.MORPH_GRADIENT, kernel)

示例:

img = cv2.imread('tu1.png')
kernel = np.ones((7,7),np.uint8)

gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
cv2.imshow('gradient', gradient)

5.6 礼帽与黑帽

礼帽 = 原始输入-开运算结果   

tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)

黑帽 = 闭运算-原始输入

blackhat  = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT, kernel)

5.7 图像梯度

5.7.1 Sobel 算子

函数:

dst = cv2.Sobel(src, ddepth, dx, dy, ksize)

参数:

        ddepth:图像的深度

        dx和dy:分别表示水平和竖直方向

        ksize:Sobel算子的大小,必须为1,3,5,7

白到黑是正数,黑到白就是负数了,所有的负数会被截断成0,所以要取绝对值

分别计算 x 和 y,再求和,不建议直接计算

示例:

img = cv2.imread('Lena.jpg',cv2.IMREAD_GRAYSCALE)

sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3) # 计算 x 梯度
sobelx = cv2.convertScaleAbs(sobelx) # 取绝对值
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3) # 计算 y 梯度
sobely = cv2.convertScaleAbs(sobely) # 取绝对值

sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0) # 求和

cv2.imshow('sobelxy',sobelxy )
cv2.waitKey(0)
cv2.destroyAllWindows()

5.7.2 Scharr 算子

示例:

img = cv2.imread('Lena.jpg',cv2.IMREAD_GRAYSCALE)

scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)
scharrx = cv2.convertScaleAbs(scharrx) 
scharry = cv2.Scharr(img,cv2.CV_64F,0,1)  
scharry = cv2.convertScaleAbs(scharry)  

scharrxy =  cv2.addWeighted(scharrx,0.5,scharry,0.5,0) 

cv2.imshow('scharrxy ',scharrxy )
cv2.waitKey(0)
cv2.destroyAllWindows()

5.7.3 laplacian 算子

示例:

img = cv2.imread('Lena.jpg',cv2.IMREAD_GRAYSCALE)

laplacian = cv2.Laplacian(img,cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)  

cv2.imshow('scharrxy ',scharrxy )
cv2.waitKey(0)
cv2.destroyAllWindows()

六、边缘检测、提取

6.1 图像金字塔

        高斯金字塔:cv2.pyrUp(img) / cv2.pyrDown(img)

                整倍数的放大缩小

        拉普拉斯金字塔:先缩小再放大为原图大小

down=cv2.pyrDown(img)
down_up=cv2.pyrUp(down)
l_1=img-down_up

6.2 Canny 边缘检测算法

        Canny算子是先平滑后求导数的方法。该算法有较好的错判率,定位性能,且对单一边缘仅有唯一响应。

算法步骤如下:

  1. 彩色图像转换为灰度图(以灰度图单通道读入);
  2. 对图像进行高斯模糊(去噪);
  3. 计算图像梯度,根据梯度计算图像边缘幅值与角度;
  4. 沿梯度方向进行非极大值抑制(边缘细化);
  5. 双阈值边缘连接处理;
  6. 通过抑制孤立的弱边缘最终完成边缘检测,二值化图像输出结果

函数:cv2.Canny(img, th1,th2,size)

参数:

        img:原图像

        th1:阈值1,较低的

        th2:阈值2,较高的

        size:可选参数,Sobel 算子的大小

示例:

img=cv2.imread("Lena.jpg",0)

v1=cv2.Canny(img,80,150)
v2=cv2.Canny(img,50,100)

res = np.hstack((v1,v2))

cv2.imshow('res',res)
cv2.waitKey(0)
cv2.destroyAllWindows()

6.3 区域生长算法

区域生长是指从某个像素出发,按照一定的准则,逐步加入邻近像素,当满足一定的条件时,区域生长终止。进而实现目标的提取。

区域生长的好坏决定于:初始点的选取,生长条件,终止条件。

算法步骤:

  1. 对图像顺序扫描,找到第一个还没有归属的像素,设该像素为(x0,y0);
  2. 以(x0,y0)为中心,考虑其4邻域像素(x,y),若满足生长条件,则将(x,y)与(x0,y0)合并(在同一区域内),同时将(x,y)压入堆栈;
  3. 从堆栈中取出一个像素,把它当作(x0,y0)返回步骤2;
  4. 当堆栈为空时,返回步骤1;
  5. 重复步骤1-4直到图像中的每个点都有归属时,生长结束

6.4 图像轮廓 cv2.findContours()

函数:

cv2.findContours(img,mode,method)

参数:

        img:原图

        mode:轮廓检索模式

                RETR_EXTERNAL :只检索最外面的轮廓;

                RETR_LIST:检索所有的轮廓,并将其保存到一条链表当中;

                RETR_CCOMP:检索所有的轮廓,并将他们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界;

                RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次;

        method:轮廓逼近方法

                CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)。

                CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是,函数只保留他们的终点部分。

示例:

img = cv2.imread('contours.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

# 旧版CV返回3个值,新版CV只返回2个值(contours 和 hierarchy)
#binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

#传入绘制图像,轮廓,轮廓索引,颜色模式,线条厚度
# 注意需要copy,要不原图会变。。。
draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2)

cv2.imshow('res',res)
cv2.waitKey(0)
cv2.destroyAllWindows()

        当轮廓过多,需要通过轮廓的面积、周长、长宽比等选择出符合条件的轮廓时,可以遍历每个轮廓,以求每个方块轮廓的质心为例:

contours, hierarchy = cv2.findContours(dst, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

# print(len(contours))

cntc = 0

# 遍历轮廓
for c in contours:
    cntc += 1
    (x, y, w, h) = cv2.boundingRect(c)  # 获取轮廓点位坐标    
    cenX = int(x + w/2)
    cenY = int(y + h/2)

    # cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2) # 画出轮廓的矩形框
    # rect = cv2.minAreaRect(c)#绘制最小矩形框
    # box = cv2.boxPoints(rect) #找矩形的四个顶点
    # box = np.int0(box)
    # cv2.drawContours(img, [box], 0, (0, 0, 255), 3)

    print('第', cntc, '个方块的质心位置为:', cenX, cenY, '面积为:', w*h)




    

七、傅里叶变换

傅里叶变换的作用:

  • 高频:变化剧烈的灰度分量,例如边界

  • 低频:变化缓慢的灰度分量,例如一片大海

滤波:

  • 低通滤波器:只保留低频,会使得图像模糊

  • 高通滤波器:只保留高频,会使得图像细节增强

        opencv中主要就是cv2.dft()和cv2.idft(),输入图像需要先转换成np.float32 格式,得到的结果中频率为0的部分会在左上角,通常要转换到中心位置,通过shift变换。

import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('lena.jpg',0)

img_float32 = np.float32(img)

dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)

magnitude_spectrum = 20*np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))

plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(magnitude_spectrum, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()

【笔记】OpenCV图像基本操作_第7张图片

import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('lena.jpg',0)

img_float32 = np.float32(img)

dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)

rows, cols = img.shape
crow, ccol = int(rows/2) , int(cols/2)     # 中心位置

# 低通滤波
mask = np.zeros((rows, cols, 2), np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1

# IDFT
fshift = dft_shift*mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])

plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img_back, cmap = 'gray')
plt.title('Result'), plt.xticks([]), plt.yticks([])

plt.show()                

【笔记】OpenCV图像基本操作_第8张图片

img = cv2.imread('lena.jpg',0)

img_float32 = np.float32(img)

dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)

rows, cols = img.shape
crow, ccol = int(rows/2) , int(cols/2)     # 中心位置

# 高通滤波
mask = np.ones((rows, cols, 2), np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 0

# IDFT
fshift = dft_shift*mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])

plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img_back, cmap = 'gray')
plt.title('Result'), plt.xticks([]), plt.yticks([])

plt.show()    

【笔记】OpenCV图像基本操作_第9张图片

你可能感兴趣的:(OpenCV图像处理,opencv,计算机视觉,图像处理,python)