• [OpenCv]初识——图像的基本处理


    目录

    前言

    一、环境搭建

    1.python包的下载

    2.Pycharm下载

    1.进入官网

    2.下载并安装pycharm

    二、初识OpenCV

    1.OpenCV介绍

    2.图片读取,电脑眼里的图片

    3.RGB颜色通道的获取

    4.图像填充

    5.图像融合

    6.图像阈值

    三、完整代码演示:

    cat.jpg

    dog.JPEG

    rode.png

    test1.py:

    test2.py:

    test3.py:

    test4.py:

    test5.py:


    前言

    学过DSP(Digital Signal Processing 数字信号处理)之后,想必紧接着就要学习DIP(Digital Image Processing)了,DSP是对一维信号的处理,而DIP则是对二维图像的处理。OpenCv支持多种语言,这里使用的是Python,旨在学习OpenCv的同时,也去多尝试使用和熟悉Python(什么?为什么没有DSP的教程?因为DSP还没学明白,而且之前做的DSP都是使用matlab来实现的)

    一、环境搭建

    1.python包的下载

    关于python的下载这里不再介绍了,下载完python之后都会附带一个pip工具。

    本次项目主要会用到opencv-python和opencv-contrib-python两个python包。还记得怎么下载吗?在之前的一篇文章中提到过下载方式,但是并没有演示

    使用python查看官网是否发布新的内容-CSDN博客

    python包可以使用pip快速而且十分方便的下载,具体步骤如下:

    step1:

    按下win+R(或者右键点“开始”,然后点运行)弹出运行框,输出cmd按下回车,进入命令提示行

    step2:

    输入以下指令下载opencv-python:

    pip install opencv-python

    包就会自动下载了(很炫酷的那种),

    step3:

    输入以下指令下载opencv-contrib-python

    pip install opencv-contrib-python

    step4:

    测试导入包:

    进入命令提示行,输入:

    python

    然后输入

    import cv2

    如果不报错,说明下载成功

    也可以输入一下代码,查看全部已经下载的python包

    pip list

    输入以下代码,退出python

    exit()

    2.Pycharm下载

    python编辑的IDE有许多:

    1. PyCharm:JetBrains 公司开发的一款强大的 Python IDE,功能丰富,支持代码补全、调试、单元测试等功能。
    2. Visual Studio Code:微软开发的轻量级代码编辑器,支持 Python 开发,通过安装插件可以实现调试、Linting 等功能。
    3. Jupyter Notebook:基于 Web 的交互式 Python 环境,适合进行数据分析和可视化编程。
    4. Spyder:科学计算和数据分析的 Python IDE,集成了 IPython 控制台、代码编辑器和变量查看器等功能。
    5. Atom:GitHub 开发的文本编辑器,通过安装插件可以实现 Python 开发的功能。
    6. Sublime Text:一款轻量级的文本编辑器,通过安装插件可以支持 Python 开发。
    7. PyDev:Eclipse 的插件,提供了Python项目支持;适合有 Eclipse 使用经验的用户。

    之前写的那个脚本是用vscode写的,对于轻量级的代码,用vscode当然没问题,但对于比较大型的项目,还是建议使用专门的IDE进行编辑。这里选择的是Pycharm

    下载Pycharm步骤如下:


    1.进入官网

    pycharm官网:

    Download PyCharm: Python IDE for Professional Developers by JetBrains

    2.下载并安装pycharm

    pycharm有专业版

    和社区版

    专业版需要收费(当然,某多几块钱就能买来破解脚本),而社区版则是免费,社区版在官网下边,得往下翻一翻才能看到。下载之后就是一个.exe,点运行,下一步下一步,选择一个安装目录,下一步下一步就可以了。

    二、初识OpenCV

    1.OpenCV介绍

    OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉库,提供了丰富的图像处理和计算机视觉算法。OpenCV 最初由 Intel 开发,后来由 Willow Garage 接手维护。它可以在多个平台上运行,包括 Windows、Linux、Mac OS 等,支持多种编程语言,如 C++、Python、Java 等。

    OpenCV 提供了许多功能和算法,包括但不限于:

    1. 图像处理:包括图像加载、保存、显示、通道分离合并、图像滤波、颜色空间转换等。
    2. 特征检测与描述:如 Harris 角点检测、SIFT、SURF、ORB 等特征点算法。
    3. 目标检测:如 Haar 特征级联、HOG 特征分类器等。
    4. 图像分割:如基于区域的分割、基于边缘的分割等。
    5. 机器学习:OpenCV 与 ML 模块结合,可用于训练和应用机器学习模型。
    6. 摄像头标定:用于相机校准和三维重建。
    7. 视频分析:包括视频捕获、处理、分析和特征跟踪等。

    OpenCV 受到广泛的应用,涵盖了计算机视觉、机器视觉、图像处理、模式识别等多个领域。开发者可以利用 OpenCV 快速实现各种图像处理和计算机视觉任务,同时通过社区的积极贡献,OpenCV 每天都在不断发展和完善。

    总的来说,OpenCV 是一个功能强大的计算机视觉库,为开发者提供了丰富的工具和算法,帮助他们在图像处理和计算机视觉任务中取得成功。

    2.图片读取,电脑眼里的图片

    我们可以使用CV2里的方法来进行读取一个图片和现实一个图片

    import cv2
    
    # 通道
    img = cv2.imread('cat.jpg')
    cv2.imshow('img ', img )
    
    cv2.waitKey(0)  # 类似延时函数,单位ms。参数为0时,为按下任意键之后结束“延时“
    cv2.destroyAllWindows()
    

    我们读取到是下边这张图片,图片只要放在.py文件相同的目录即可。

    我们知道,图片是有一个一个像素点组成的,RGB三原色组成了一张彩色的图片,对于黑白的图片,只需要知道亮度就可以获得一张图片。这里的RGB是三个数组,数组的大小等于图片的像素大小,数组里的每一个值的取值都为0到255,0对应黑,255对应最亮,也就是纯白。就像这样:

    RGB三个数组,也就是对应三个颜色通道,三个颜色通道合在一起,就组成一张图片。

    cv2.imread()函数,读取出来的就是一个三维数组,记录着RGB三个数组的值。

    保存处理好的图片可以使用以下代码:
     

    cv2.imwrite("out_img.jpg", cur_img)  # 图片保存

    使用PS也可以查看每个通道的信息:

    3.RGB颜色通道的获取

    RGB颜色通道的获取有两组简答的方法,一是直接将通过cv2.imread读取到的img的其中两个维度置为0,只留下其中一个维度,那就可以得到只包含其中一个颜色通道的数据了,需要注意的是,cv2读取的图片是GBR,跟我们常见的RGB刚好是反着的三个数组,因此在处理时需要注意,尤其是在使用非cv2的图片显示函数时,一定要先将GBR转化为RGB(下边的代码会提到)

    import cv2
    
    # 通道
    img = cv2.imread('cat.jpg')
    
    cur_img = img.copy()
    # 让b和g都变为0,那就剩下r了,下同
    cur_img[:, :, 0] = 0  # b g r
    cur_img[:, :, 1] = 0  # b g r
    cv2.imshow('r', cur_img)
    cv2.waitKey(0)  # 类似延时函数,单位ms。参数为0时,为按下任意键之后结束“延时“
    cv2.destroyAllWindows()

    这里演示的是其中一个通道的获取,其他通道的获取也类似。

    此外,cv2也提供了一个方法来获取RGB,注意这个方法获取到也是GBR,我们也可以通过GBR的值来重新合成一张图片

    import cv2
    
    # 通道
    img = cv2.imread('cat.jpg')
    b, g, r = cv2.split(img)  # 获取b g r三个通道
    img2 = cv2.merge([b, g, r])  # 根据bgr还原图像
    cv2.imshow('img', img2)
    cv2.waitKey(0)

    依次绘制RGB三个通道的图片如图:

    4.图像填充

    图像填充简单点说,就是把图像四周填充上东西。OpenCv内置的有填充的方法,并提供了多种填充方式

    import cv2
    import matplotlib.pyplot as plt
    
    # 图像填充
    img = cv2.imread('cat.jpg')
    img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # 将读取到的bgr转化为rgb
    top_size, bottom_size, left_size, right_size = (100, 100, 100, 100)  # 设置需要填充的大小
    
    # 图像填充
    cropped_img1 = cv2.copyMakeBorder(img_rgb, top_size, bottom_size, left_size, right_size,
                                      borderType=cv2.BORDER_REPLICATE)
    cropped_img2 = cv2.copyMakeBorder(img_rgb, top_size, bottom_size, left_size, right_size,
                                      borderType=cv2.BORDER_REFLECT)
    cropped_img3 = cv2.copyMakeBorder(img_rgb, top_size, bottom_size, left_size, right_size,
                                      borderType=cv2.BORDER_REFLECT_101)
    cropped_img4 = cv2.copyMakeBorder(img_rgb, top_size, bottom_size, left_size, right_size,
                                      borderType=cv2.BORDER_WRAP)
    cropped_img5 = cv2.copyMakeBorder(img_rgb, top_size, bottom_size, left_size, right_size,
                                      borderType=cv2.BORDER_CONSTANT)
    
    # BORDER_REPLICATE:复制法,也就是复制最边缘像素。
    # BORDER_REFLECT:反射法, 对感兴趣的图像中的像素在两边进行复制
    # BORDER_REFLECT_101: 反射法, 也就是以最边缘像素为轴, 对称
    # BORDER_WRAP: 外包装法
    # BORDER_CONSTANT:常量法,常数值填充
    fig, axs = plt.subplots(nrows=2, ncols=3)  # 分区绘制图像
    
    axs[0, 0].imshow(img_rgb)
    axs[0, 1].imshow(cropped_img1)
    axs[0, 2].imshow(cropped_img2)
    axs[1, 0].imshow(cropped_img3)
    axs[1, 1].imshow(cropped_img4)
    axs[1, 2].imshow(cropped_img5)
    
    plt.show()
    
    cv2.waitKey(0)

    这里使用了plot绘图,并使用subplots进行分区(跟Matlab的方法好像很像,至少名字很像),因此在绘图前,需要将cv2读取到的GBR转化为RGB,也就是:

    img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 将读取到的bgr转化为rgb

    绘制出来的结果为:

    5.图像融合

    图像融合是图像处理的一部分,这里以图像融合为例来介绍。

    刚才已经提到了计算机眼里的图像是三个数组,那我们可不可以对数组进行操作呢?比如把数组的值+10?当然可以,处理起来就跟处理一个数组一样。同样,我们也可以将两个同样大小的数组进行融合,注意必须是同样大小的数组。我们这里在导入一个dog的图像

    直接使用.shpe查看两个图像数组的大小

    import cv2
    
    # 图像融合和简单计算
    img1 = cv2.imread('cat.jpg')
    img2 = cv2.imread('dog.JPEG')
    
    print(f"img1: {img1.shape}")
    print(f"img2: {img2.shape}")

    我们发现两个图像不一样大,狗的图像更大,那我们就裁剪一下狗的图片,使之与猫一样大,然后使用cv2.add进行融合

    img1 = cv2.resize(img1, (650, 433))  # 调整狗的大小,使之与猫的大小一致
    
    # img2 = cv2.resize(img2, (0, 0), fx=0.5, fy=0.5)  # 也可以不指定调整后的大小,而是指定调整后x,y的倍数
    
    cv2.imshow('img', cv2.add(img1, img2))  # 显示融合后的图像(巨丑)
    cv2.waitKey(0)

    这里要介绍一下cv2.add()与直接img1+img2的区别了,刚才已经提到,数组内的值取值范围是0到255,使用add函数,如果两个图形某个位置的值相加大于255,则会被置为255,而直接img1+img2的话,则得到的某个位置的值为该位置相加的值%255.

    相加之后的图片巨丑,就不在演示了

    6.图像阈值

    图像阈值是一个大头,很多处理都会用到

    cv2内置的也有阈值除了函数,跟图像填充一样,也提供了多种处理方式

    阈值的除了主要是为了将图片二值化(或者说我遇到最多的就是二值化和边沿检查)

    在现实图片之前,还是需要将RGB转化为GBR。threshold函数的第一个参数应是某一个通道的值。这次读取的图片是一个智能车比赛时的赛道

    import cv2
    import matplotlib.pyplot as plt
    
    # 阈值
    img = cv2.imread('rode.png')
    b, g, r = cv2.split(img)
    
    # 二值化
    ret1, thresh1 = cv2.threshold(b, thresh=127, maxval=255, type=cv2.THRESH_BINARY)
    ret2, thresh2 = cv2.threshold(b, thresh=127, maxval=255, type=cv2.THRESH_BINARY_INV)
    ret3, thresh3 = cv2.threshold(b, thresh=127, maxval=255, type=cv2.THRESH_TRUNC)
    ret4, thresh4 = cv2.threshold(b, thresh=127, maxval=255, type=cv2.THRESH_TOZERO)
    ret5, thresh5 = cv2.threshold(b, thresh=123, maxval=255, type=cv2.THRESH_TOZERO_INV)
    # cv2.THRESH_BINARY超过阈值部分取maxval(最大值),否则取O
    # cV2.THRESH_BINARY_INV THRESH_BINARY的反转
    # cv2.THRESH_TRUNC大于阈值部分设为阈值,否则不变
    # cv2.THRESH_TOZERO大于阈值部分不改变,否则设为O
    # cV2.THRESH_TOZERO_INV THRESH_TOZERO的反转
    
    # 将 BGR 转化为 RGB
    img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    thresh1_rgb = cv2.cvtColor(thresh1, cv2.COLOR_RGB2BGR)
    thresh2_rgb = cv2.cvtColor(thresh2, cv2.COLOR_RGB2BGR)
    thresh3_rgb = cv2.cvtColor(thresh3, cv2.COLOR_RGB2BGR)
    thresh4_rgb = cv2.cvtColor(thresh4, cv2.COLOR_RGB2BGR)
    thresh5_rgb = cv2.cvtColor(thresh5, cv2.COLOR_RGB2BGR)
    
    # 显示图像
    fig, axs = plt.subplots(nrows=2, ncols=3)
    axs[0, 0].imshow(img_rgb)
    axs[0, 1].imshow(thresh1_rgb)
    axs[0, 2].imshow(thresh2_rgb)
    axs[1, 0].imshow(thresh3_rgb)
    axs[1, 1].imshow(thresh4_rgb)
    axs[1, 2].imshow(thresh5_rgb)
    
    plt.show()  # 绘制图像运行

    结果如下图:

    三、完整代码演示:

    cat.jpg

    dog.JPEG

    rode.png

    test1.py:

    1. import cv2
    2. # 通道
    3. img = cv2.imread('cat.jpg')
    4. cur_img = img.copy()
    5. # 让b和g都变为0,那就剩下r了,下同
    6. cur_img[:, :, 0] = 0 # b g r
    7. cur_img[:, :, 1] = 0 # b g r
    8. cv2.imshow('r', cur_img)
    9. cur_img = img.copy()
    10. cur_img[:, :, 0] = 0 # b g r
    11. cur_img[:, :, 2] = 0 # b g r
    12. cv2.imshow('g', cur_img)
    13. cur_img = img.copy()
    14. cur_img[:, :, 1] = 0 # b g r
    15. cur_img[:, :, 2] = 0 # b g r
    16. cv2.imshow('b', cur_img)
    17. cv2.waitKey(0) # 类似延时函数,单位ms。参数为0时,为按下任意键之后结束“延时“
    18. cv2.destroyAllWindows()
    19. # cv2.imwrite("out_img.jpg", cur_img) # 图片保存

    test2.py:

    1. import cv2
    2. # 通道
    3. img = cv2.imread('cat.jpg')
    4. b, g, r = cv2.split(img) # 获取b g r三个通道
    5. # bb = img[:, :, 0] # 或者这样获取
    6. print(b)
    7. print(f"b.shape: {b.shape}")
    8. print(f"g.shape: {g.shape}")
    9. print(f"r.shape: {r.shape}")
    10. print(f"img.shape: {img.shape}")
    11. img2 = cv2.merge([b, g, r]) # 根据bgr还原图像
    12. cv2.imshow('img', img2)
    13. cv2.waitKey(0)

    test3.py:

    1. import cv2
    2. import matplotlib.pyplot as plt
    3. # 图像填充
    4. img = cv2.imread('cat.jpg')
    5. img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 将读取到的bgr转化为rgb
    6. top_size, bottom_size, left_size, right_size = (100, 100, 100, 100) # 设置需要填充的大小
    7. # 图像填充
    8. cropped_img1 = cv2.copyMakeBorder(img_rgb, top_size, bottom_size, left_size, right_size,
    9. borderType=cv2.BORDER_REPLICATE)
    10. cropped_img2 = cv2.copyMakeBorder(img_rgb, top_size, bottom_size, left_size, right_size,
    11. borderType=cv2.BORDER_REFLECT)
    12. cropped_img3 = cv2.copyMakeBorder(img_rgb, top_size, bottom_size, left_size, right_size,
    13. borderType=cv2.BORDER_REFLECT_101)
    14. cropped_img4 = cv2.copyMakeBorder(img_rgb, top_size, bottom_size, left_size, right_size,
    15. borderType=cv2.BORDER_WRAP)
    16. cropped_img5 = cv2.copyMakeBorder(img_rgb, top_size, bottom_size, left_size, right_size,
    17. borderType=cv2.BORDER_CONSTANT)
    18. # BORDER_REPLICATE:复制法,也就是复制最边缘像素。
    19. # BORDER_REFLECT:反射法, 对感兴趣的图像中的像素在两边进行复制
    20. # BORDER_REFLECT_101: 反射法, 也就是以最边缘像素为轴, 对称
    21. # BORDER_WRAP: 外包装法
    22. # BORDER_CONSTANT:常量法,常数值填充
    23. fig, axs = plt.subplots(nrows=2, ncols=3) # 绘制图像
    24. axs[0, 0].imshow(img_rgb)
    25. axs[0, 1].imshow(cropped_img1)
    26. axs[0, 2].imshow(cropped_img2)
    27. axs[1, 0].imshow(cropped_img3)
    28. axs[1, 1].imshow(cropped_img4)
    29. axs[1, 2].imshow(cropped_img5)
    30. plt.show()
    31. cv2.waitKey(0)

    test4.py:

    1. import cv2
    2. # 图像融合和简单计算
    3. img1 = cv2.imread('cat.jpg')
    4. img2 = cv2.imread('dog.JPEG')
    5. print(f"img1: {img1.shape}")
    6. print(f"img2: {img2.shape}")
    7. img1 = cv2.resize(img1, (650, 433)) # 调整狗的大小,使之与猫的大小一致
    8. # img2 = cv2.resize(img2, (0, 0), fx=0.5, fy=0.5) # 也可以不指定调整后的大小,而是指定调整后x,y的倍数
    9. cv2.imshow('img', cv2.add(img1, img2)) # 显示融合后的图像(巨丑)
    10. cv2.waitKey(0)

    test5.py:

    1. import cv2
    2. import matplotlib.pyplot as plt
    3. # 阈值
    4. img = cv2.imread('rode.png')
    5. b, g, r = cv2.split(img)
    6. # 二值化
    7. ret1, thresh1 = cv2.threshold(b, thresh=127, maxval=255, type=cv2.THRESH_BINARY)
    8. ret2, thresh2 = cv2.threshold(b, thresh=127, maxval=255, type=cv2.THRESH_BINARY_INV)
    9. ret3, thresh3 = cv2.threshold(b, thresh=127, maxval=255, type=cv2.THRESH_TRUNC)
    10. ret4, thresh4 = cv2.threshold(b, thresh=127, maxval=255, type=cv2.THRESH_TOZERO)
    11. ret5, thresh5 = cv2.threshold(b, thresh=123, maxval=255, type=cv2.THRESH_TOZERO_INV)
    12. # cv2.THRESH_BINARY超过阈值部分取maxval(最大值),否则取O
    13. # cV2.THRESH_BINARY_INV THRESH_BINARY的反转
    14. # cv2.THRESH_TRUNC大于阈值部分设为阈值,否则不变
    15. # cv2.THRESH_TOZERO大于阈值部分不改变,否则设为O
    16. # cV2.THRESH_TOZERO_INV THRESH_TOZERO的反转
    17. # 将 BGR 转化为 RGB
    18. img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    19. thresh1_rgb = cv2.cvtColor(thresh1, cv2.COLOR_RGB2BGR)
    20. thresh2_rgb = cv2.cvtColor(thresh2, cv2.COLOR_RGB2BGR)
    21. thresh3_rgb = cv2.cvtColor(thresh3, cv2.COLOR_RGB2BGR)
    22. thresh4_rgb = cv2.cvtColor(thresh4, cv2.COLOR_RGB2BGR)
    23. thresh5_rgb = cv2.cvtColor(thresh5, cv2.COLOR_RGB2BGR)
    24. # 显示图像
    25. fig, axs = plt.subplots(nrows=2, ncols=3)
    26. axs[0, 0].imshow(img_rgb)
    27. axs[0, 1].imshow(thresh1_rgb)
    28. axs[0, 2].imshow(thresh2_rgb)
    29. axs[1, 0].imshow(thresh3_rgb)
    30. axs[1, 1].imshow(thresh4_rgb)
    31. axs[1, 2].imshow(thresh5_rgb)
    32. plt.show() # 绘制图像



     

  • 相关阅读:
    每日4道算法题——第005天
    弘辽科技:弘辽小编来和大家分享补单的三大技巧啦!
    C++ —— 命名空间
    GoLang 单元测试打桩和 mock
    群晖 NAS 外网访问设置 - 腾讯 DNSPod
    【华为OD机试真题 JS】计算面积
    Redis对象的数据结构及其原理汇总
    面向对象原型和函数原型
    docker 镜像 overview
    上云网关EasyNTS遇到IP冲突时,如何正确更改IP地址?
  • 原文地址:https://blog.csdn.net/qq_73427280/article/details/136354088