美文网首页
OpenCV常用操作

OpenCV常用操作

作者: CV算法恩仇录 | 来源:发表于2022-03-03 17:26 被阅读0次

    原创:杨其泓

    1 OpenCV入门基础

    1.1 OpenCV简介

    OpenCV的全称是Open Source Computer Vision Library,是一个跨平台的计算机视觉库。OpenCV是由英特尔公司发起并参与开发,以BSD许可证授权发行,可以在商业和研究领域中免费使用。OpenCV可用于开发实时的图像处理、计算机视觉以及模式识别程序。OpenCV-Python是OpenCV的Python API,集成了Python语言和C++语言的最优特征,致力于支持Python解决计算机视觉问题。

    1.2 Python安装OpenCV

    在Python中安装OpenCV十分便捷,可以直接使用:pip install opencv-pythonconda insatll opencv-python即可。

    注:默认安装最新版,如有特定版本需求,可使用pip install opencv-python==4.1.2

    在成功安装OpenCV后,可以在Python编译器中键入如下内容,查看是否安装成功:

    import cv2
    print(cv2.__version__)
    

    1.3 图片的读取、显示与保存

    1. 图像读取

    使用OpenCV读取图片文件,可以使用函数cv2.imread(filepath, flags),例如:

    image=cv2.imread('test.jpg')
    

    该函数共接收两个输入,即要读入图片的完整路径和读入图片的方式,常用方式包括以下三种

    • cv2.IMREAD_COLOR:默认参数,读入一副彩色图片,忽略alpha通道
    • cv2.IMREAD_GRAYSCALE:读入灰度图片
    • cv2.IMREAD_UNCHANGED:顾名思义,读入完整图片,包括alpha通道

    OpenCV读取图片后返回的是一个numpy数组,对于彩色图像,数组为三维数组,其形状(shape)为(图像高,图像宽,3),其中3代表图片的RGB三个通道,由于OpenCV在存储彩色图像时,默认通道顺序为BGR,在进行图像处理时要注意不要使用错误的通道顺序。

    1. 图像显示

    使用OpenCV显示图片文件,可以使用函数cv2.imshow(wname, img),例如:

    cv2.imshow('Test_image', image)
    

    在多数时候,我们会将上述API搭配cv2.waitKey()cv2.destroyAllWindows()使用,waitKey顾名思义,就是等待键盘键入,而destroyAllWindows就是关闭所有已经显示的窗口,搭配这两个API后即可实现:显示一张图片,并在键盘键入任意值后关闭图片的效果。

    下面就是使用OpenCV读入图片并展示的样例代码:

    import cv2
    image_BGR = cv2.imread('KKB.jpeg', cv2.IMREAD_COLOR)
    image_gray = cv2.imread('KKB.jpeg', cv2.IMREAD_GRAYSCALE)
    cv2.imshow('BGR', image_BGR)
    cv2.imshow('gray', image_gray)
    cv2.waitKey()
    cv2.destroyAllWindows()
    

    输出效果如下:

    1. 图像保存

    使用OpenCV显示图片文件,可以使用函数cv2.imwrite(file, img, num),例如:

    cv2.imwrite('testimage.jpeg', image_BGR)
    # cv2.imwrite('testimage.jpeg', image_BGR, [int(cv2.IMWRITE_JPEG_QUALITY), 95])
    # cv2.imwrite('testimage.jpeg', image_BGR, [int(cv2.IMWRITE_PNG_COMPRESSION), 9])
    

    这个API有三个参数:第一个参数是要保存的文件路径,第二个参数是要保存的图像。第三个参数是可选参数,它针对特定的格式:对于JPEG,其表示的是图像的质量,用0 - 100的整数表示,默认95;对于png ,第三个参数表示的是压缩级别,默认为3。

    2 图像处理基础

    2.1 像素处理

    1. 访问像素

    在OpenCV中,我们可以直接以索引的方式访问图像的像素。例如我们访问刚才读取的图片(200, 200)坐标位置(左上角为坐标系原点)的像素可是使用:

    import cv2
    image_BGR = cv2.imread('KKB.jpeg', cv2.IMREAD_COLOR)
    print(image_BGR[200,200])
    >>> [246 218 177]
    

    可见,在(200, 200)坐标位置所对应的三通道像素值分别为B:246,G:218,R:177。

    1. 修改像素

    图像像素值的修改也十分简单,下面我们将原始图片中的一部分区域修改为红色(0, 0, 255):

    import cv2
    image_BGR = cv2.imread('KKB.jpeg', cv2.IMREAD_COLOR)
    image_BGR[100:200, 100:200] = [0,0,255]
    cv2.imshow('BGR', image_BGR)
    cv2.waitKey()
    cv2.destroyAllWindows()
    

    所得到的结果为:

    2.2 图像属性

    1. 图像形状

    图像的形状可以通过image.shape获得,例如:

    import cv2
    image_BGR = cv2.imread('KKB.jpeg', cv2.IMREAD_COLOR)
    print(image_BGR.shape)
    >>> (684, 1067, 3)
    

    可以看到,刚才我们打开的那张图片的高是684像素,宽是1067像素,通道数为3。

    1. 像素数目

    图像的像素数目可以理解为图像中的像素值总量,也就是行*列*通道,可以通过image.size获得,例如:

    import cv2
    image_BGR = cv2.imread('KKB.jpeg', cv2.IMREAD_COLOR)
    print(image_BGR.size)
    >>> 2189484
    

    我们来验证一下,刚才我们打开的那张图片的高是684像素,宽是1067像素,通道数为3,那他的像素数量应为这三者的乘积,即为684*1067*3=2189484,与上述代码中计算所得相同。

    1. 图像类型

    图像的类型可以通过image.dtype获得,例如:

    import cv2
    image_BGR = cv2.imread('KKB.jpeg', cv2.IMREAD_COLOR)
    print(image_BGR.dtype)
    >>> uint8
    

    由此可见,这张图片的属性是uint8。

    3 图像运算

    3.1 图像加法

    我们知道,以uint8形式存储的图片的取值范围是[0, 255],即0代表纯黑,1代表纯白,0~1之间的值则表示由深到浅的灰色。那么在对图像做加法的时候,就会产生一个问题:像素值为100的图片+像素值为100的图片,可以获得像素值为200的图片,但如果是150+150,两张图片相加之后的像素值超出255的范围怎么办?在这时候,有两种解决方案。

    1. 取模运算

    一般来说我们可以直接使用+进行取模运算,即image_c = image_a + image_b。取模运算顾名思义,就是对运算结果取模,此时两个像素值的相加大家可以理解为:

    def image_add(pixel_a, pixel_b):
        if pixel_a + pixel_b <= 255:
            return pixel_a + pixel_b
        if pixel_a + pixel_b > 255:
            return (pixel_a + pixel_b) % 255
    

    也就是在不超出255范围时:100+100=200,在超出255范围时:150+150=(150+150)\%255=45

    1. 饱和运算

    饱和运算就更好理解了,两个像素值相加,如果超出255的限制,则直接取255。使用cv2.add(a, b)即可进行饱和运算。

    取模运算和饱和运算的代码及效果图如下:

    import cv2
    image_a = cv2.imread('dog.jpeg', cv2.IMREAD_GRAYSCALE)
    image_b= cv2.imread('cat.jpeg', cv2.IMREAD_GRAYSCALE)
    
    image_c = image_a + image_b
    image_d = cv2.add(image_a, image_b)
    
    cv2.imshow('image_a', image_a)
    cv2.imshow('image_b', image_b)
    cv2.imshow('image_c', image_c)
    cv2.imshow('image_d', image_d)
    cv2.waitKey()
    cv2.destroyAllWindows()
    

    3.2 图像融合

    图像融合其实也是图像加法的一种, 图像融合为两张图像赋予了不同的权重,从而使图像具有混合或透明的感觉。在OpenCV中,可以使用cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]])来进行图像融合,此函数会依据下列表达式来进行运算dst = src1 * alpha + src2 * beta + gamma,也就是对图片1和图片2分别乘一个系数后相加,并添加gamma作为偏置。图像融合的代码及效果图如下:

    import cv2
    image_a = cv2.imread('dog.jpeg', cv2.IMREAD_GRAYSCALE)
    image_b= cv2.imread('cat.jpeg', cv2.IMREAD_GRAYSCALE)
    
    image_c = cv2.addWeighted(image_a, 0.5, image_b, 0.5, 0)
    
    cv2.imshow('image_a', image_a)
    cv2.imshow('image_b', image_b)
    cv2.imshow('image_c', image_c)
    cv2.waitKey()
    cv2.destroyAllWindows()
    

    4 图像几何变换

    4.1 图像缩放

    图像缩放其实就是改变图像的大小、形状,可以用下列API来实现:

    Image = cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])
    

    这个API的参数较多,但其实很好理解,下面就是API的参数解释:

    • Image:输出图像
    • src:输入图像
    • dsize:输出图像的尺寸
    • fx:横坐标缩放比例
    • fy:纵坐标缩放比例
    • interpolation:缩放方式

    在这些参数中,输入、输出图像都很好理解,输出图像的尺寸dsize是(宽,高),fxfy一般可直接使用0-1的缩放比例,值得注意的一点是,在给定dsize时,就不用另外输入缩放比例了,而想使用缩放比例时,disze应输入None(不可不输入)。缩放方式一般不填,直接使用默认值即可,其他缩放方式如下:

    • INTER_NEAREST 最近邻插值
    • INTER_LINEAR 双线性插值(默认设置)
    • INTER_AREA 使用像素区域关系进行重采样。 它可能是图像抽取的首选方法,因为它会产生无云纹理的结果。 但是当图像缩放时,它类似于INTER_NEAREST方法。
    • INTER_CUBIC 4x4像素邻域的双三次插值
    • INTER_LANCZOS4 8x8像素邻域的Lanczos插值

    图像缩放的代码如下:

    import cv2
    image = cv2.imread('dog.jpeg', cv2.IMREAD_GRAYSCALE)
    print(image.shape)
    >>> (224, 225)
    image = cv2.resize(image,(175,175))
    print(image.shape)
    >>> (175, 175)
    

    4.2 图像翻转

    图像的翻转可以使用cv2.flip(src, flipCode)实现,在这个API中需要输入一个翻转的模式flipCode:

    • flipCode为0代表垂直翻转(沿X轴翻转);
    • flipCode大于0代表水平翻转(沿Y轴翻转);
    • flipCode小于0代表水平垂直翻转(先沿X轴翻转,再沿Y轴翻转,等价于旋转180°)

    图片翻转的代码及样例图如下:

    import cv2
    image= cv2.imread('cat.jpeg', cv2.IMREAD_GRAYSCALE)
    image = cv2.resize(image,(300,300))
    image_a = cv2.flip(image, -1)
    image_b = cv2.flip(image, 0)
    image_c = cv2.flip(image, 1)
    
    cv2.imshow('image', image)
    cv2.imshow('image_a', image_a)
    cv2.imshow('image_b', image_b)
    cv2.imshow('image_c', image_c)
    cv2.waitKey()
    cv2.destroyAllWindows()
    

    4.3 图像旋转

    图像的旋转比翻转要复杂一些,图像旋转过程中,要先求得旋转矩阵,而后在通过仿射变化函数对图像进行旋转。

    cv2.getRotationMatrix2D(center, angle, scale) # 旋转矩阵
    cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst # 仿射变化
    

    参数说明

    getRotationMatrix2D:

    • center–表示旋转的中心点
    • angle–表示旋转的角度degrees
    • scale–图像缩放因子

    warpAffine:

    • src – 输入的图像
    • M – 2 X 3 的变换矩阵.
    • dsize – 输出的图像的size大小
    • dst – 输出的图像
    • flags – 输出图像的插值方法
    • borderMode – 图像边界的处理方式
    • borderValue – 当图像边界处理方式为BORDER_CONSTANT 时的填充值

    图片旋转的代码及样例图如下(顺时针转90度):

    import cv2
    image = cv2.imread('dog.jpeg', cv2.IMREAD_GRAYSCALE)
    h, w = image.shape
    
    M = cv2.getRotationMatrix2D((w//2,h//2),-90,1.0)
    dst = cv2.warpAffine(image,M,(w,h))
    
    cv2.imshow('dst', dst)
    cv2.waitKey()
    cv2.destroyAllWindows()
    
    image

    5 图像平滑处理

    5.1 均值滤波

    均值滤波是最简单的滤波器,它取卷积核区域下所有像素的平均值并替换中心元素,均值滤波的代码及样例图如下:

    import cv2
    image = cv2.imread('dog.jpeg')
    img_mean = cv2.blur(image, (5,5)) # 原图,核心大小
    cv2.imshow('image', image)
    cv2.imshow('img_mean', img_mean)
    cv2.waitKey()
    cv2.destroyAllWindows()
    

    5.2 中值滤波

    中值滤波器是一种非线性滤波器,它的基本原理是:选择待处理像素的一个邻域中各像素值的中值来代替待处理的像素。它能使某像素的灰度值与周围领域内的像素比较接近,从而消除一些孤立的噪声点,所以中值滤波器能够很好的消除椒盐噪声。中值滤波的代码及样例图如下:

    import cv2
    image = cv2.imread('dog.jpeg')
    img_median = cv2.medianBlur(image, 5) # 原图,核心大小
    cv2.imshow('image', image)
    cv2.imshow('img_median', img_median)
    cv2.waitKey()
    cv2.destroyAllWindows()
    

    5.3 高斯滤波

    高斯滤波也是一种常见的滤波器,与中值滤波不同的是,它是使用高斯核心来计算的:
    h(x,y)=e^{\frac{-(x^2+y^2)}{2\sigma^2}}
    其中(x,y)是图像中的点的坐标, \sigma为标准差。x和y都是代表以核中心点为坐标原点的坐标值,对于而言 \sigma,当 \sigma比较小的时候,生成的高斯模板中心的系数比较大,而周围的系数比较小,这样对图像的平滑效果不明显。当比较大时 \sigma,生成的模板的各个系数相差就不是很大,比较类似于均值模板,对图像的平滑效果比较明显。高斯滤波的代码及样例图如下:

    import cv2
    image = cv2.imread('dog.jpeg')
    img_Guassian = cv2.GaussianBlur(image,(5,5),0) # 原图,核心大小,sigma
    cv2.imshow('image', image)
    cv2.imshow('img_Guassian', img_Guassian)
    cv2.waitKey()
    cv2.destroyAllWindows()
    

    5.4 双边滤波

    双边滤波是一种非线性滤波方法,是结合了图像的邻近度和像素值相似度的一种折中,在滤除噪声的同时可以保留原图的边缘信息。整个双边滤波是由两个函数构成:一个函数是由空间距离决定的滤波器系数,另外一个诗由像素差值决定的滤波器系数,双边滤波具体计算过程在这里就不赘述了。双边滤波的代码及样例图如下:

    import cv2
    image = cv2.imread('dog.jpeg')
    img_bilater = cv2.bilateralFilter(image,9,75,75)
    cv2.imshow('image', image)
    cv2.imshow('img_bilater', img_bilater)
    cv2.waitKey()
    cv2.destroyAllWindows()
    

    相关文章

      网友评论

          本文标题:OpenCV常用操作

          本文链接:https://www.haomeiwen.com/subject/lbrurrtx.html