当前位置: 首页 > article >正文

图像处理学习笔记(一)

本文主要介绍,以供读者能够理解该技术的定义、原理、应用。

🎬个人简介:一个全栈工程师的升级之路!
📋个人专栏:ISP处理
🎀CSDN主页 发狂的小花
🌄人生秘诀:学习的本质就是极致重复!

目录

1椒盐噪声

2 中值模糊

3 高斯滤波的优化方法(分离高斯滤波)

3 PIL 库

4 Matplotlib

5 Jupyter notebook

6 Python图像处理步骤

7 Numpy 数组和普通数组的区别

7 .bss ..data段

1椒盐噪声

椒盐噪声是**图像中常见的一种噪声,表现为随机分布的白色或黑色像素点**。其特点和处理方法如下:

1. **特点**:

   - 表现为图像中的白点或黑点,即在亮的区域出现黑色像素,或在暗的区域出现白色像素。

   - 这种噪声通常由图像传感器、传输信道或解码处理等环节产生。

   - 由于信号脉冲强度的影响而产生的噪声,算法上相对简单,但会对图像质量造成影响。

2. **处理方法**:

   - **中值滤波**:是一种常用的去除椒盐噪声的方法,通过替换像素值为其邻近像素的中值来消除噪声。

   - **排序滤波**:类似于中值滤波,通过排序邻近像素值并选择中间值替换原有像素值来减少噪声的影响。

总的来说,了解和掌握椒盐噪声的特点和处理方法对于图像处理是非常重要的,因为噪声会直接影响到图像分割、特征提取、图像识别等后续处理步骤的效果。

2 中值模糊

中值模糊的原理是**基于统计排序的非线性滤波方法**。

中值模糊是一种图像处理技术,它通过**选取像素邻域内的中值来替代中心像素的值**,从而达到模糊图像的效果。这种方法对于去除图像中的椒盐噪声(即随机出现的白点或黑点)特别有效。与线性滤波器如均值模糊和高斯模糊不同,中值模糊不会对图像造成模糊问题,因为它不是通过平均像素值来实现平滑效果,而是通过选择一系列像素中的中值来实现。

具体来说,中值模糊的处理步骤如下:

1. **选择滑动窗口大小**:确定一个奇数大小的窗口,这个窗口将在图像上滑动,用于选取像素进行排序。

2. **对窗口内像素进行排序**:在每个窗口位置,对窗口内的像素值进行排序。

3. **取中值替代中心像素**:将排序后的中值作为当前窗口中心像素的新值。

4. **移动窗口**:窗口按照一定步长移动到下一个位置,重复上述过程,直到整个图像处理完毕。

总的来说,中值模糊因其独特的处理方式,在保持图像边缘锐度的同时,能有效减少噪声,尤其适用于那些细节丰富或包含大量尖角、线条的图像。由于其不依赖于像素的统计特性,因此在不知道噪声具体分布的情况下也能使用,这在一定程度上增加了其适用性和灵活性。在实际应用中,中值模糊通常通过OpenCV库中的`cv2.medianBlur()`函数来实现,该函数接受一个参数,即滑动窗口的大小。

3 高斯滤波的优化方法(分离高斯滤波)

高斯滤波的优化方法通常包括以下几种:

分离高斯滤波:由于高斯函数具有可分离性,可以将二维高斯滤波器分解为两个一维滤波器的顺序应用,这大大减少了计算量。首先应用一个一维高斯滤波器进行水平方向的卷积,然后再用另一个一维高斯滤波器进行垂直方向的卷积。

StackBlur近似:这种方法通过多次应用均值滤波器来近似高斯滤波的效果。虽然这种方法并不是精确的高斯滤波,但在某些情况下可以作为一种快速近似方法。

频域高斯滤波:在频率域中实现高斯滤波也是一种优化方法。通过将图像转换到频率域,应用高斯滤波器,然后再转换回空间域,有时可以更高效地处理图像。

此外,对于小半径的高斯滤波器,可以通过查表或其他优化算法来减少计算量,因为小半径意味着需要处理的数据量更少。

#include <iostream>
#include <string>
#include <vector>
#include <chrono>
#include <opencv2/opencv.hpp>
#include <stdio.h>
#include <math.h>
#include <stdint.h>

using namespace std;
using namespace cv;


// 定义常量
#define PI 3.14159265358979323846
#define SIGMA 1.0
#define KERNEL_SIZE 5

// 定义一维高斯函数
float gaussian(int x, float sigma) {
    return exp(-x * x / (2 * sigma * sigma)) / (sqrt(2 * PI) * sigma);
}

// 定义二维高斯函数
float gaussian2d(int x, int y, float sigma) {
    return exp(-(x * x + y * y) / (2 * sigma * sigma)) / (2 * PI * sigma * sigma);
}

// 定义分离高斯滤波函数
void separable_gaussian_filter(unsigned char* input, unsigned char* output, int width, int height, float sigma) {
    // 创建水平方向的高斯核
    float kernel[KERNEL_SIZE];
    for (int i = 0; i < KERNEL_SIZE; i++) {
        kernel[i] = gaussian(i - KERNEL_SIZE / 2, sigma);
    }

    // 对输入图像进行水平方向的卷积
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            float sum = 0;
            for (int k = 0; k < KERNEL_SIZE; k++) {
                int index = x + k - KERNEL_SIZE / 2;
                if (index >= 0 && index < width) {
                    sum += input[y * width + index] * kernel[k];
                }
            }
            output[y * width + x] = (unsigned char)(sum + 0.5); // 四舍五入取整
        }
    }

    // 创建垂直方向的高斯核
    float kernel2[KERNEL_SIZE];
    for (int i = 0; i < KERNEL_SIZE; i++) {
        kernel2[i] = gaussian(i - KERNEL_SIZE / 2, sigma);
    }

    // 对输出图像进行垂直方向的卷积
    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {
            float sum = 0;
            for (int k = 0; k < KERNEL_SIZE; k++) {
                int index = y + k - KERNEL_SIZE / 2;
                if (index >= 0 && index < height) {
                    sum += output[index * width + x] * kernel2[k];
                }
            }
            output[y * width + x] = (unsigned char)(sum + 0.5); // 四舍五入取整
        }
    }
}

int main() {
    // 读取输入图像数据(此处省略)

    uint8_t inputBuff[640*400];
    uint8_t outputBuff[640*400];
    int width = 640; // 图像宽度
    int height = 400; // 图像高度

    Mat img = imread("./data/left.png", 0);
    
    cout << img.cols << img.rows << endl;// 640x400,400 rows 640 cols

    for (int i = 0;i < height;i++)
    {
        for (int j = 0;j < width;j++)
        {
            inputBuff[i*width+j] = img.ptr<uint8_t>(i)[j];
        }
    }
    unsigned char* input = inputBuff; // 输入图像数据数组
    unsigned char* output = outputBuff; // 输出图像数据数组

   

    // 调用分离高斯滤波函数
    separable_gaussian_filter(input, output, width, height, SIGMA);
    
    cv::Mat out_image = cv::Mat(cv::Size(640,400), CV_8UC1, output);

    cv::imshow("Image",img);
    cv::imshow("OUTImage",out_image);
    cv::waitKey(0);



    return 0;
}

3 PIL 库

PIL库,全称Python Imaging Library,是一个功能强大且易于使用的Python图像处理库。

PIL库最初仅支持Python 2.7版本,但由于其长时间未更新,社区的志愿者们在PIL的基础上创建了兼容Python 3的版本,即Pillow库。Pillow库是PIL的一个友好分支,它提供了与PIL相似的接口,并且增加了许多新特性和改进,同时支持Python 3。Pillow库是目前广泛使用的Python图像处理库,它提供了一系列强大的功能,包括但不限于:

图像的打开、读写和保存:可以使用Pillow库中的Image模块轻松地打开各种格式的图像文件,并进行读写操作。

图像转换:Pillow支持图像格式的转换,以及颜色空间的转换,如RGB与灰度之间的转换。

图像编辑:可以对图像进行裁剪、旋转、翻转、调整大小等各种编辑操作。

图像合成:可以将多个图像层叠合并,或者将图像的一部分粘贴到另一张图像上。

绘制几何图形和文字:Pillow库还提供了在图像上绘制几何形状和文字的功能。

4 Matplotlib

**Matplotlib是一个强大的Python绘图库,广泛用于数据可视化**。

Matplotlib是Python中一个非常流行的绘图库,它提供了丰富的功能来帮助用户创建各种静态、动态甚至交互式的图表。以下是关于Matplotlib的一些详细信息:

- **作用**:Matplotlib能够生成多种类型的图形,如线图、散点图、柱状图、饼图等。它支持多种操作系统和后端,可以输出到屏幕或者保存为各种格式的图像文件。此外,Matplotlib可以与NumPy和SciPy等科学计算库集成,使得数据分析和机器学习领域的可视化任务变得更加便捷。

- **安装方法**:安装Matplotlib通常可以通过pip命令来完成,使用`pip install matplotlib`即可轻松安装。不过,由于Matplotlib依赖于一些其他包,可能需要确保系统中已经安装了这些依赖包。

- **基本用法**:在绘制图形时,通常会结合使用Matplotlib中的`pyplot`模块,它提供了类似于MATLAB的接口。例如,要绘制一个简单的正弦函数图形,可以使用`plt.plot(x, np.sin(x))`来绘制曲线,其中`x`是一组数值,`np.sin(x)`是对应的正弦值。

- **应用场景**:Matplotlib适用于需要进行数据可视化的各种场景,特别是在数据科学和机器学习领域。它可以帮助研究人员和开发者更好地理解数据模式和趋势,以及在模型训练过程中监控进度和性能。

总的来说,Matplotlib是一个非常有用的工具,无论是对于数据分析师还是科研人员,都是一个很好的选择。通过学习Matplotlib的基本用法和高级特性,可以有效地提升数据分析和可视化的能力。

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

def gaussian(x, mu, sigma):
    return 1 / (sigma * np.sqrt(2 * np.pi)) * np.exp(-(x - mu) ** 2 / (2 * sigma ** 2))


def gaussian_2d(x, y, mu, sigma):
    return 1 / (2 * np.pi * sigma ** 2) * np.exp(-((x - mu[0]) ** 2 + (y - mu[1]) ** 2) / (2 * sigma ** 2))


x = np.linspace(-10, 10, 1000)
y = gaussian(x, 0, 1)

plt.plot(x, y)
plt.xlabel('x')
plt.ylabel('y')
plt.title('Gaussian Function')
# plt.show()
plt.savefig('Gaussian1d.jpg')


x = np.linspace(-10, 10, 100)
y = np.linspace(-10, 10, 100)
X, Y = np.meshgrid(x, y)
Z = gaussian_2d(X, Y, [0, 0], 1)

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X, Y, Z)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
# plt.show()
plt.savefig('Gaussian2d.jpg')

5 Jupyter notebook

在Jupyter Notebook中运行代码并显示图像的具体步骤如下:

打开终端或命令提示符。

输入jupyter notebook并按Enter键,这将在你的默认浏览器中打开Jupyter Notebook。

在Jupyter Notebook的主界面,点击右上角的“New”按钮,然后选择“Python 3”(或者你安装的其他Python版本)。

在新打开的Notebook中,你可以在单元格中编写Python代码。

为了显示图像,你可以使用matplotlib库。确保你已经安装了matplotlib和numpy(如果需要的话)。

选中包含代码的单元格,按Shift + Enter运行单元格中的代码。

如果一切正常,图像将在单元格下方显示。

在Notebook的菜单栏中,点击“File”然后选择“Save and Checkpoint”来保存你的工作。

完成工作后,可以在菜单栏中选择“File” -> “Close and Halt”来关闭Notebook。

如果你在Notebook中运行matplotlib绘图代码,图像应该会直接在输出区域显示。如果在Jupyter Notebook中仍然遇到问题,请确保你的matplotlib后端配置正确。你可以通过以

6 Python图像处理步骤

import matplotlib.pyplot as plt
from PIL import Image
import numpy as np

# 打开彩色图像
image = Image.open('./cat.png')

# 将图像转换为 NumPy 数组
image_array = np.array(image)

# 分离通道
red_channel = image_array[:, :, 0]

green_channel = image_array[:, :, 1]

blue_channel = image_array[:, :, 2]

# 显示原始图像和各个通道
plt.subplot(221), plt.imshow(image), plt.title('Original Image')

plt.subplot(222), plt.imshow(blue_channel, cmap='Blues'), plt.title('Blue Channel')

plt.subplot(223), plt.imshow(green_channel, cmap='Greens'), plt.title('Green Channel')

plt.subplot(224), plt.imshow(red_channel, cmap='Reds'), plt.title('Red Channel')


# 保存图像到文件

plt.savefig('output.png')

这段代码的主要功能是打开一张彩色图像,将其转换为NumPy数组,然后分离出红、绿、蓝三个通道,并将原始图像和各个通道的图像显示出来。

详细解释:

1. 导入所需的库:PIL(Python Imaging Library)用于处理图像,numpy用于处理数组,matplotlib.pyplot用于绘图。

2. 使用PIL库的Image模块打开一张名为'cat.png'的彩色图像。

3. 将图像转换为NumPy数组,方便后续处理。

4. 分离出图像的红、绿、蓝三个通道。

5. 使用matplotlib.pyplot绘制子图,分别显示原始图像和各个通道的图像。

6. 最后一行代码注释掉了`plt.show()`,改为使用`plt.savefig('rgb.png')`将图像保存为'rgb.png'文件。

7 Numpy 数组和普通数组的区别

Numpy中的数组(ndarray)与Python原生的数组(list)主要有以下区别:

1. 存储方式:ndarray是连续的内存块,而list则是指向对象的指针的集合。这意味着ndarray在存储和访问数据时更加高效,因为它们在内存中的位置是连续的,而不是分散的。

2. 数据类型:ndarray中的所有元素都必须具有相同的数据类型,而list可以包含不同类型的元素。这使得ndarray在执行数值计算时更加高效,因为它不需要处理不同数据类型的转换。

3. 函数库支持:Numpy提供了大量用于操作ndarray的函数,这些函数在执行数学运算、线性代数、统计等方面的任务时非常高效。相比之下,list没有这些专门针对其结构的函数库。

4. 性能:由于ndarray的存储方式和数据类型的特点,它们在执行大规模数值计算时通常比list更快。此外,Numpy还利用了向量化计算的优势,可以对整个数组进行操作,而无需使用循环。

5. 索引和切片:ndarray支持更灵活的索引和切片操作,例如整数数组、布尔数组等。这使得在处理数据时更加方便和高效。

6. 广播:Numpy具有广播功能,可以自动将形状不同的数组扩展到相同的形状并进行逐元素操作。这使得在进行数学运算时更加方便,而无需手动处理不同形状的数组。

总之,Numpy中的ndarray与Python原生的list相比,具有更高的性能、更丰富的功能和更好的兼容性。在进行数值计算和数据处理时,ndarray通常是更好的选择。

7 .bss ..data段

1、bss段(Block Started Symbol,意为“以符号开始的块”),只是简单维护地址空间中开始和结束的地址,在实际运行对内存区域有效地清零即可。bss段存放 全局未初始化/初始化为0、静态未初始化/初始化为0的变量, 在磁盘上并不占用相应的磁盘空间。

2、data段,存放的是 全局初始化(初始化非0)、静态初始化(初始化非0)的变量,在磁盘中占用相应的磁盘空间,这些变量在程序开始之前具有具体值,是可执行文件的一部分,当程序执行运行时,将可执行文件加载到内存中,读取相应的变量值。

3、bss段维护的是0值的数据变量,不需要占据相应的磁盘空间,data段存放的是具体有效非0值,需要占据相应的磁盘空间,以供程序运行时加载读取相应的值。两者分开维护管理, 有效地降低可执行文件占据磁盘的容量,否则初始化化数据项越多,可执行文件越大,运行时加载到内存所需要的时间消耗越大。

🌈我的分享也就到此结束啦🌈
如果我的分享也能对你有帮助,那就太好了!
若有不足,还请大家多多指正,我们一起学习交流!
📢未来的富豪们:点赞👍→收藏⭐→关注🔍,如果能评论下就太惊喜了!
感谢大家的观看和支持!最后,☺祝愿大家每天有钱赚!!!欢迎关注、关注!


http://www.kler.cn/a/274699.html

相关文章:

  • 精通 Numpy 数组:详解数据类型查看、转换与索引要点
  • 内置函数.
  • SQL Server 解决游标性能问题的替代方案
  • [数据结构] 链表
  • Spring Boot--06--整合Swagger
  • 理解 EXPLAIN
  • LLM不仅仅是聊天应用,它们也可以提升制药销售团队的客户触达。
  • 【微服务】Gateway服务网关
  • [Python人工智能] 四十三.命名实体识别 (4)利用bert4keras构建Bert+BiLSTM-CRF实体识别模型
  • Python实战:TensorFlow与Keras
  • unity 学习笔记 4.坐标系
  • springboot2.7集成es8 https方式绕过证书访问集群
  • 32串口学习
  • 【图论】【深度优先搜索】【换根法】2858. 可以到达每一个节点的最少边反转次数
  • SpringMVC的执行原理
  • 「实战应用」如何用DHTMLX构建自定义JavaScript甘特图(二)
  • React简介
  • 在Ubuntu20.04(原为cuda12.0, gcc9.几版本和g++9.几版本)下先安装cuda9.0后再配置gcc-5环境
  • 图书馆管理系统 1.架构项目以及加搭建项目
  • centos安装docker-compose
  • Selenium不同版本配置自动下载驱动及打包细节
  • Spring的炼气之路(炼气三层)
  • 3、java虚拟机-类的生命周期-初始化阶段(与程序员有关)
  • JRTLIS登录
  • 前端小白的学习之路(lessscss)
  • 百度交易中台之系统对账篇