Advertisement

图像处理技术研究与实现——python+opencv

阅读量:

背景介绍

21世纪是一个充满信息的时代,图像作为人类感知世界的视觉基础,是人类获取信息、表达信息和传递信息的重要手段。处理图像,可以帮助我们更好地获取信息,也可以使我们更客观、准确地认识世界。

图像处理作为计算机视觉领域的重要分支,在各个行业中扮演着越来越重要的角色。从医疗诊断、自动驾驶、安防监控到人工智能领域的图像识别,图像处理无处不在。

OpenCV

  • OpenCV是一个开源的计算机视觉库,它包含了丰富的图像处理和计算机视觉功能,支持多种操作系统(Linux、Windows、Mac OS)
  • OpenCV用C++语言编写,它的主要接口也是C++语言。该库也有大量的Python, Java and MATLAB的接口
  • 具有通用的图象/视频载入、保存和获取模块
  • 具有基本的数字图象处理能力,如可进行滤波、边缘检测、角点检测、采样与差值、色彩转换、形态操作、直方图和图象金字塔等操作

本文所有代码都是基于Pyhon的OpenCV库,conda install opencv

有时候安装opencv得使用conda install -c conda-forge opencv 这个命令
不然可能会因为和python版本不兼容问题导致导入不了cv2

图像色彩转换

灰度图像生成
  • 计算机中,图像由一个个像素组成
  • 彩色图像有R,G,B三个颜色通道叠加而成
  • 灰度图像只有一个颜色通道,显示范围从纯黑到纯白,0-255(8位灰度图,28)

如图所示,这是两张10×10像素的图
在这里插入图片描述

图像灰度化就是使彩色图像的R、G、B三个分量相等的过程,opencv内置了转换函数

复制代码
    # 将彩色图像转为灰度图
    import cv2
    import matplotlib.pyplot as plt
    import matplotlib.image as mpimg
    import numpy as np
    
    image=cv2.imread('lena.png')
    gray_image=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    
    # OpenCV读取的图像默认是BGR格式(蓝、绿、红)
    # 而matplotlib的imshow方法预期的是RGB格式
    
    image_rgb=image[:,:,::-1]
    
    fig, axs = plt.subplots(1, 2, figsize=(10, 5))
    # axs[0].imshow(cv2.cvtColor(image,cv2.COLOR_BGR2RGB)) #所以这里需要将BGR转为RGB格式
    axs[0].imshow(image_rgb) #这样也能转换
    axs[0].set_title('Original Image')
    axs[0].axis('off')
    
    axs[1].imshow(gray_image,cmap='gray')  # 灰度图需要指定颜色映射
    axs[1].set_title('Grayscale Image')
    axs[1].axis('off')
    
    plt.tight_layout() #自动调整子图间距
    plt.show()
    
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/iMLtul8WaUCrZjxAnP64h0mpTeoR.png)
在这里插入图片描述
图像二值化

图像二值化即将图像转换为只有黑白两种颜色,设定一个阈值,灰度值超过这个阈值的转换为白色,低于阈值的转为黑色

复制代码
    #生成黑白颜色图
    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib as mpl
    mpl.rcParams["font.sans-serif"]=["SimHei"]
    mpl.rcParams["axes.unicode_minus"]=False
    
    image=cv2.imread("lena_gray.png")
    
    """固定阈值二值化"""
    _, binary = cv2.threshold(image, 125, 255, cv2.THRESH_BINARY)
    
    thresh=125
    image[image>thresh]=255
    image[image<=thresh]=0
    
    plt.figure(figsize=(10, 5))
    
    # 原始灰度图
    plt.subplot(1, 2, 1)
    plt.imshow(image, cmap='gray')
    plt.title('原始灰度图')
    plt.axis('off')
    
    plt.subplot(1,2,2)
    plt.imshow(binary)
    plt.title('黑白图')
    plt.axis('off')
    
    plt.tight_layout()
    plt.show()
    
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/c87Ml2Ft4WhAbeK5aE09xozBiyqS.png)
在这里插入图片描述
灰度图彩色化

如何从灰度图生成彩色图?需要自定义颜色映射关系
下面代码展示几种经典的颜色映射关系

复制代码
    import cv2
    import matplotlib.pyplot as plt
    import numpy as np
    import matplotlib as mpl
    mpl.rcParams["font.sans-serif"]=["SimHei"]
    mpl.rcParams["axes.unicode_minus"]=False
    
    # 读取灰度图像
    gray_image =  plt.imread('lena_gray_512.tif') #cv2.imread('lena.png', cv2.IMREAD_GRAYSCALE)
    
    # 创建子图
    fig, axs = plt.subplots(2, 2, figsize=(10, 10))
    
    # 原始灰度图像
    axs[0,0].imshow(gray_image, cmap='gray')
    axs[0,0].set_title('原始灰度图')
    axs[0,0].axis('off')
    
    # 应用不同伪彩色映射
    axs[0,1].imshow(gray_image, cmap='jet')     # 彩虹色映射
    axs[0,1].set_title('Jet 彩虹色映射')
    axs[0,1].axis('off')
    
    axs[1,0].imshow(gray_image, cmap='viridis') # 黄绿色映射
    axs[1,0].set_title('Viridis 黄绿色映射')
    axs[1,0].axis('off')
    
    axs[1,1].imshow(gray_image, cmap='hot')     # 热力图映射
    axs[1,1].set_title('Hot 热力图映射')
    axs[1,1].axis('off')
    
    plt.tight_layout()
    # plt.savefig('pseudo_color_comparison.png', dpi=120)
    plt.show()
    
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/PufzIbUhwmkC0NYiqAd2LQp3OxGa.png)
在这里插入图片描述

还可以自定义随机颜色映射关系

复制代码
    #为灰度图重新生成颜色
    import cv2
    import matplotlib.pyplot as plt
    from matplotlib.colors import ListedColormap
    import numpy as np
    
    # image=cv2.imread('lena_gray.png')
    gray_image =  plt.imread('lena_gray_512.tif')
    
    # 确保图像数据在0-1范围内(matplotlib要求)
    if gray_image.dtype == np.uint8:
    gray_image = gray_image.astype(np.float32) / 255.0
    elif np.max(gray_image) > 1.0:
    gray_image = gray_image / np.max(gray_image)
    
    # 方法1:生成随机颜色映射(每个灰度值对应随机颜色)
    def create_random_colormap(num_colors=256):
    """创建随机颜色映射表"""
    # 生成随机RGB颜色(0-1范围)
    random_colors = np.random.rand(num_colors, 3)
    
    # 确保黑色和白色固定
    random_colors[0] = [0, 0, 0]   # 黑色
    random_colors[-1] = [1, 1, 1]  # 白色
    
    return ListedColormap(random_colors)
    
    # 方法2:生成平滑过渡的随机颜色映射
    def create_smooth_random_colormap(num_colors=256):
    """创建平滑过渡的随机颜色映射"""
    # 生成关键颜色点
    key_points = np.random.rand(5, 3)  # 5个随机RGB颜色点
    
    # 在关键点之间插值
    colormap_values = np.zeros((num_colors, 3))
    for i in range(3):  # 对R,G,B通道分别处理
        colormap_values[:, i] = np.interp(
            np.linspace(0, 1, num_colors),
            np.linspace(0, 1, len(key_points)),
            key_points[:, i]
        )
    
    # 确保黑色和白色固定
    colormap_values[0] = [0, 0, 0]   # 黑色
    colormap_values[-1] = [1, 1, 1]  # 白色
    
    return ListedColormap(colormap_values)
    
    random_cmap=create_random_colormap()
    smooth_cmap = create_smooth_random_colormap()
    # 生成随机 RGB 图像
    rgb_image = np.random.rand(256, 3)
    
    fig, axs = plt.subplots(1, 2, figsize=(10, 5))
    # axs[0].imshow(cv2.cvtColor(image,cv2.COLOR_BGR2RGB))
    axs[0].imshow(gray_image,cmap='gray')
    axs[0].set_title('Original Image')
    axs[0].axis('off')
    
    axs[1].imshow(gray_image,cmap=smooth_cmap)  # 灰度图需要指定颜色映射
    axs[1].set_title('随机颜色映射')
    axs[1].axis('off')
    
    
    plt.tight_layout() #自动调整子图间距
    plt.show()
    
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/2eNwvcS5jBQmz6fsgWxrU3hZAPuG.png)
在这里插入图片描述

图像滤波

  • 图像滤波是一种去除图像噪声和干扰的技术,也可用来平滑图像
  • 常见的噪声有两种,椒盐噪声和高斯噪声 ,椒盐噪声通常由图像传感器、传输信道或解码环节产生,是一种随机出现的白点或黑点(最大最小值),高斯噪声是一种符合正态分布的随机噪声,通常由传感器在拍摄过程中因光照不足、温度变化或电子干扰引起,无法避免。

下面是两张分别具有高斯噪声和椒盐噪声的图片
在这里插入图片描述在这里插入图片描述

高斯滤波

高斯滤波是最常用的一种滤波方式,适合处理高斯噪声,原理这里就不多讲了,感兴趣的可以去自行了解

复制代码
    # 高斯滤波
    import cv2
    import matplotlib.pyplot as plt
    import matplotlib as mpl
    mpl.rcParams["font.sans-serif"]=["SimHei"]
    mpl.rcParams["axes.unicode_minus"]=False
    
    # 读取图像
    img = cv2.imread('gaussian_noisy.jpg')
    # 均值滤波 会使图像模糊化
    # blurred=cv2.blur(img,(5,5))
    # 高斯滤波
    blurred = cv2.GaussianBlur(img, (5, 5), 0)
    # 显示原始图像和滤波后的图像
    # cv2.imshow('Original Image', img)
    # cv2.imshow('Blurred Image', blurred)
    
    plt.figure(figsize=(10, 5))
    plt.subplot(1, 2, 1)
    plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
    plt.title('原始图')
    plt.axis('off')
    
    plt.subplot(1,2,2)
    plt.imshow(cv2.cvtColor(blurred,cv2.COLOR_BGR2RGB))
    plt.title('滤波图')
    plt.axis('off')
    
    plt.tight_layout()
    plt.show()
    
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/1XUMZsS9vBRolkqCg6VNOaQTE7HF.png)
在这里插入图片描述
均值滤波

均值滤波是最简单的滤波方式,就是每个像素取周围像素的平均值,均值滤波可以使图像模糊化以便得到感兴趣物体的粗略描述。

复制代码
    # 均值滤波
    import cv2
    import matplotlib.pyplot as plt
    import matplotlib as mpl
    mpl.rcParams["font.sans-serif"]=["SimHei"]
    mpl.rcParams["axes.unicode_minus"]=False
    
    # 读取图像
    img = cv2.imread('gaussian_noisy.jpg')
    # 均值滤波 会使图像模糊化
    blurred=cv2.blur(img,(5,5))
    # 高斯滤波
    # blurred = cv2.GaussianBlur(img, (5, 5), 0)
    # 显示原始图像和滤波后的图像
    # cv2.imshow('Original Image', img)
    # cv2.imshow('Blurred Image', blurred)
    
    plt.figure(figsize=(10, 5))
    plt.subplot(1, 2, 1)
    plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
    plt.title('原始图')
    plt.axis('off')
    
    plt.subplot(1,2,2)
    plt.imshow(cv2.cvtColor(blurred,cv2.COLOR_BGR2RGB))
    plt.title('滤波图')
    plt.axis('off')
    
    plt.tight_layout()
    plt.show()
    
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/Hmhkb7pD0WBfjUCxySrOJowQtuVv.png)
在这里插入图片描述
中值滤波
  • 中值滤波是取周围像素排序后的中间值
  • 因为取中间值不受极值影响,中值滤波很适合去除椒盐噪声
复制代码
    import cv2
    import matplotlib.pyplot as plt
    import matplotlib as mpl
    mpl.rcParams["font.sans-serif"]=["SimHei"]
    mpl.rcParams["axes.unicode_minus"]=False
    
    # 读取图像
    img = cv2.imread('salt_pepper_noisy.jpg')
    # 均值滤波 会使图像模糊化
    # blurred=cv2.blur(img,(5,5))
    # 高斯滤波
    # blurred = cv2.GaussianBlur(img, (5, 5), 0)
    # 中值滤波
    blurred=cv2.medianBlur(img,5)
    
    # cv2.imshow('Original Image', img)
    # cv2.imshow('Blurred Image', blurred)
    # cv2.waitKey(0)
    # cv2.destroyAllWindows()
    plt.figure(figsize=(10, 5))
    plt.subplot(1, 2, 1)
    plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
    plt.title('原始图')
    plt.axis('off')
    
    plt.subplot(1,2,2)
    plt.imshow(cv2.cvtColor(blurred,cv2.COLOR_BGR2RGB))
    plt.title('滤波图')
    plt.axis('off')
    
    plt.tight_layout()
    plt.show()
    
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/D7vkB25YhcOWSRalGeP6XdsKfVrt.png)
在这里插入图片描述
双边滤波

双边滤波是一种可以保持图像边缘清晰 的去噪方法,和高斯滤波类似,也是通过计算像素和领域像素的加权平均实现的,不同的是,双边滤波的权重矩阵权值由两部分组成,空间距离和色彩差异,距离越远,权重越小,色彩差别越大,权重越小。

复制代码
    # 双边滤波 保持边缘清晰的同时减少图片中的噪声
    
    import cv2
    import matplotlib.pyplot as plt
    import matplotlib as mpl
    mpl.rcParams["font.sans-serif"]=["SimHei"]
    mpl.rcParams["axes.unicode_minus"]=False
    
    # 读取图像
    # img = cv2.imread('cat.4038.jpg')
    img = cv2.imread('gaussian_noisy.jpg')
    # 均值滤波 会使图像模糊化
    # blurred=cv2.blur(img,(5,5))
    # 高斯滤波
    # blurred = cv2.GaussianBlur(img, (5, 5), 0)
    # 中值滤波
    # blurred=cv2.medianBlur(img,5)
    
    blurred=cv2.bilateralFilter(img,9,75,75)
    
    # cv2.imshow('Original Image', img)
    # cv2.imshow('Blurred Image', blurred)
    # cv2.waitKey(0)
    # cv2.destroyAllWindows()
    plt.figure(figsize=(10, 5))
    plt.subplot(1, 2, 1)
    plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
    plt.title('原始图')
    plt.axis('off')
    
    plt.subplot(1,2,2)
    plt.imshow(cv2.cvtColor(blurred,cv2.COLOR_BGR2RGB))
    plt.title('滤波图')
    plt.axis('off')
    
    plt.tight_layout()
    plt.show()
    
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/7deMrB54E9JfIGaCp0xNQq3oHuKc.png)
在这里插入图片描述

图像增强

非锐化掩蔽

非锐化掩蔽是图像锐化中最专业、最常用的方法之一,可拆解为三个步骤:

复制代码
    创建模糊版本:用高斯模糊创建原始图像的模糊版本
    提取高频细节:原始图像减去模糊图像得到高频细节
    加权混合:将原始图像与0.5倍的高频细节相加
    
    
复制代码
    import cv2
    import numpy as np
    from matplotlib import pyplot as plt
    
    # 1. 读取彩色图像
    image = cv2.imread('lena.png')  # 读取BGR格式图像
    
    # 2. 创建锐化卷积核(拉普拉斯增强核)
    # sharpening_kernel = np.array([
    #     [0, -1, 0],
    #     [-1, 5, -1],  # 中心值5 = 1(保留原像素) + 4(增强系数)
    #     [0, -1, 0]
    # ])
    
    # 3. 应用卷积(进行拉普拉斯锐化)
    
    blurred = cv2.GaussianBlur(image, (0,0), 3)
    sharpened_image = cv2.addWeighted(image, 1.5, blurred, -0.5, 0)
    
    # sharpened_image = cv2.filter2D(image, -1, sharpening_kernel)
    
    # 4. 显示结果
    plt.figure(figsize=(10, 5))
    
    # 原始图像(需转换为RGB显示)
    plt.subplot(1, 2, 1)
    plt.title('Original Image')
    plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
    plt.axis('off')
    
    # 锐化结果(需转换为RGB显示)
    plt.subplot(1, 2, 2)
    plt.title('Sharpened Image')
    plt.imshow(cv2.cvtColor(sharpened_image, cv2.COLOR_BGR2RGB))
    plt.axis('off')
    plt.tight_layout()
    plt.show()
    
    
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/zvXbk2Iw5B9c6DOCHRlrxmFaesKn.png)
在这里插入图片描述
限制对比度自适应直方图均衡化CLAHE

是传统直方图均衡化HE的改进版本,可拆解为四个步骤

复制代码
     - 局部处理:将输入图像划分为许多小矩形区域tiles
     - 局部直方图均衡化:对每个独立的tile执行直方图均衡化
     - 对比度限制:每个tile直方图设置裁剪限制度
     - 插值:计算像素的最终灰度值
    
    
复制代码
    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    
    def clahe_enhancement(img, clip_limit=2.0, grid_size=(8,8)):
    if len(img.shape) == 2: #检测是否为灰度图
        clahe = cv2.createCLAHE(clipLimit=clip_limit, tileGridSize=grid_size)
        return clahe.apply(img)
    else:
        lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB) #LAB颜色空间,亮度(L)颜色(A,B)
        l, a, b = cv2.split(lab)
        clahe = cv2.createCLAHE(clipLimit=clip_limit, tileGridSize=grid_size)
        l_clahe = clahe.apply(l) #只增强亮度通道 避免颜色失真
        return cv2.cvtColor(cv2.merge([l_clahe, a, b]), cv2.COLOR_LAB2BGR)
    
    image=cv2.imread('lena.png')
    
    # # 对比度增强
    # alpha=1.2
    # enhanced_image=np.clip(alpha*image,0,255).astype(np.uint8)
    
    # # 亮度调整
    # beta=50
    # adjusted_image=cv2.add(enhanced_image,beta)
    
    # # 饱和度增强
    # hsv_image=cv2.cvtColor(adjusted_image,cv2.COLOR_BGR2HSV)
    # hsv_image[:,:,1]=1.5*hsv_image[:,:,1]
    # saturated_image=cv2.cvtColor(hsv_image,cv2.COLOR_HSV2BGR)
    
    enhanced = clahe_enhancement(image, clip_limit=2.0, grid_size=(8,8))
    
    plt.figure(figsize=(10, 5))
    plt.subplot(1,2,1)
    plt.title('Original Image')
    plt.imshow(cv2.cvtColor(image,cv2.COLOR_BGR2RGB))
    plt.axis('off')
    
    plt.subplot(1,2,2)
    plt.title('clahe Image')
    plt.imshow(cv2.cvtColor(enhanced,cv2.COLOR_BGR2RGB))
    plt.axis('off')
    
    plt.tight_layout()
    plt.show()
    
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-16/M7Klr53eVWvIfzmSAcHd8bRsBJ4T.png)
在这里插入图片描述

总结

本文只探讨了图像处理常见的一些基本技术,对一些复杂的图像处理算法未做研究,望诸君见谅。

全部评论 (0)

还没有任何评论哟~