OpenCV图像变换与处理实战方法记录

 更新时间:2024年12月10日 09:02:22   作者:悠着,大嘟嘟  
这篇文章主要给大家介绍了关于OpenCV图像变换与处理实战的相关资料,包括重映射、缩放、旋转、颜色变换、边缘检测、高斯模糊、图像锐化和颜色反转等,通过实例分析详细解释了这些功能的实现原理和代码实现,需要的朋友可以参考下

前言

在计算机视觉的绚丽舞台上,OpenCV 无疑是一颗耀眼的明星,它赋予开发者操控图像、挖掘视觉信息的超强能力。在正式深入那些令人惊叹的代码实例前,咱们先来夯实理论基础,为后续实操筑牢根基。

一、OpenCV 基础与图像处理概览

OpenCV(Open Source Computer Vision Library),开源计算机视觉库,犹如一座装满图像处理 “神器” 的百宝箱。历经多年迭代、无数开发者打磨,它横跨多平台,用 C++、Python 等热门语言编写接口,贴合不同编程习惯,揽下计算机视觉八成基础任务,从简单图像读取、存储,到复杂目标检测、图像识别,统统不在话下。

图像处理本质是对图像像素的精心雕琢。图像存于计算机里,像整齐排列的 “像素方阵”,每个像素怀揣颜色、亮度信息。咱做图像处理,就是巧妙改变这些像素属性。像调亮度,是给像素亮度值做加法;改颜色,是调配红、绿、蓝分量。手段不同,目的一致:让图像契合特定需求,或美轮美奂,或信息精准。

二、图像变换理论精析

(一)重映射(Remapping)

重映射堪称图像坐标的 “乾坤大挪移”。正常图像像素按行列规则站位,重映射打破常规,依自定义映射规则给像素 “搬家”。核心原理是新建两张和原图像同尺寸 “坐标图”(src_x、src_y),记录新位置,好比导游图,指引像素 “迁移” 方向。这操作实用性拉满,制造波浪、扭曲特效时大显身手,让画面瞬间灵动。

(二)缩放(Scaling)

缩放直白说就是给图像 “放大缩小”。数学上,按比例因子(scale_x、scale_y)改变行列像素数量,近的像素合并变小图,间隔插值变 “长胖” 成大图。插值算法是关键,常见线性插值(cv::INTER_LINEAR),像经验老到的裁缝,凭周边像素信息,算出新增像素 “恰当脸色”,保图像平滑过渡。

(三)旋转(Rotation)

旋转让图像优雅 “转身”。先锁定旋转中心,多为图像几何中心,再用旋转矩阵(由 cv::getRotationMatrix2D 生成)做 “旋转指令”。这矩阵蕴含旋转角度、缩放比例信息,结合仿射变换(cv::warpAffine),像素依指令乖乖就位,画面流畅旋动,毫无违和 “晕车感”。

三、图像增强与特征提取理论

(一)颜色变换(Color Conversion)

颜色空间多如繁星,常见 RGB、HSV、灰度等。RGB 重色彩呈现,HSV 便颜色调整,灰度则聚焦亮度信息,抛弃色彩冗余。像转灰度图,用 cv::cvtColor 一键 “褪色”,按人眼亮度感知规则,加权融合 RGB 值,提取关键亮度,利于后续处理,还能降数据量、提处理速度。

(二)边缘检测(Edge Detection)

边缘是图像 “骨架”,藏关键轮廓信息。边缘检测算法像敏锐侦探,紧盯像素灰度突变处。Canny 算法是王牌,设低、高双阈值,梯度超 “高线” 锁定边缘;在 “低线” 与 “高线” 间,看连接情况甄别;低过 “低线”,直接 pass。经非极大值抑制、双阈值筛选,精准揪出边缘,给目标识别、图像分割铺好路。

(三)高斯模糊(Gaussian Blur)

现实图像常带噪声,像老照片划痕、数码噪点。高斯模糊化身 “美颜磨皮师”,用高斯函数生成权重核,中心像素权重高、周边递减,加权平均周边像素值,模糊图像、柔化噪声,让画面细腻干净,为后续精准处理清障。

(四)图像锐化(Image Sharpening)

锐化是模糊 “克星”,找回图像丢失细节。原理是强化高频分量,弱化低频。靠特制卷积核(如文中 3x3 核)卷积图像,中心像素 “突出”,周边反向调节,反差凸显边缘细节,照片、扫描文档处理后清晰度飙升。

(五)颜色反转(Color Inversion)

颜色反转堪称图像 “镜像世界”,简单粗暴按位取反像素值。白变黑、黑变白,各颜色分量翻转,特定艺术创作、负片效果模拟时,轻松拿捏氛围感。

三、实例分析

1. 定义常量 M_PI

#ifndef M_PI
#define M_PI 3.14159265358979323846 // 如果未定义 M_PI,则手动定义
#endif

这段代码的目的是确保在编译过程中,如果 M_PI 常量未被定义,则手动定义它为圆周率的值。这在一些情况下是必要的,因为不同的编译器和环境可能对某些常量的定义有所不同。

2. 重映射图像创建波形效果

void wave(const cv::Mat& img, cv::Mat& res, const std::string& wave_type, double amplitude, double frequency) {
    cv::Mat src_x(img.rows, img.cols, CV_32F);
    cv::Mat src_y(img.rows, img.cols, CV_32F);

    for (int i = 0; i < img.rows; i++) {
        for (int j = 0; j < img.cols; j++) {
            src_x.at<float>(i, j) = static_cast<float>(j);
            double wave_value = 0.0;

            if (wave_type == "sine") {
                wave_value = amplitude * sin(frequency * static_cast<double>(j)); // 正弦波
            }
            else if (wave_type == "cosine") {
                wave_value = amplitude * cos(frequency * static_cast<double>(j)); // 余弦波
            }
            else if (wave_type == "triangle") {
                wave_value = amplitude * (2.0 / M_PI) * asin(sin(frequency * static_cast<double>(j))); // 三角波
            }
            else if (wave_type == "sawtooth") {
                wave_value = amplitude * (2.0 * (j / static_cast<double>(img.cols)) - 1.0); // 锯齿波
            }

            src_y.at<float>(i, j) = static_cast<float>(i + wave_value);
        }
    }

    cv::remap(img, res, src_x, src_y, cv::INTER_LINEAR);
}

这个函数用于创建不同类型的波形效果,通过重映射图像的像素坐标来实现。它接受输入图像 img、输出图像 res、波形类型 wave_type、振幅 amplitude 和频率 frequency 作为参数。

首先,创建两个与输入图像大小相同的矩阵 src_x 和 src_y,分别用于存储重映射后的 x 和 y 坐标。然后,通过双层循环遍历输入图像的每个像素。对于每个像素,将 src_x 中的对应值设置为当前像素的 x 坐标,并根据 wave_type 的不同计算出波形的值 wave_value。最后,将 src_y 中的对应值设置为当前像素的 y 坐标加上波形值。

最后,使用 cv::remap 函数根据 src_x 和 src_y 矩阵对输入图像进行重映射,得到输出图像 res

3. 缩放图像

void scale(const cv::Mat& img, cv::Mat& res, double scale_x, double scale_y) {
    cv::resize(img, res, cv::Size(), scale_x, scale_y, cv::INTER_LINEAR);
}

这个函数用于缩放图像。它接受输入图像 img、输出图像 res、水平缩放比例 scale_x 和垂直缩放比例 scale_y 作为参数。

使用 cv::resize 函数对输入图像进行缩放,将输出图像的大小设置为输入图像的大小乘以缩放比例。这里使用 cv::INTER_LINEAR 插值方法,以获得较为平滑的缩放效果。

4. 旋转图像

void rotate1(const cv::Mat& img, cv::Mat& res, double angle) {
    cv::Point2f center(img.cols / 2.0, img.rows / 2.0);
    cv::Mat rot = cv::getRotationMatrix2D(center, angle, 1.0);
    cv::warpAffine(img, res, rot, img.size());
}

这个函数用于旋转图像。它接受输入图像 img、输出图像 res 和旋转角度 angle 作为参数。

首先,计算图像的中心坐标。然后,使用 cv::getRotationMatrix2D 函数创建一个旋转矩阵 rot,该矩阵将图像绕中心旋转指定的角度。最后,使用 cv::warpAffine 函数根据旋转矩阵对输入图像进行仿射变换,得到输出图像 res

5. 颜色变换(灰度图)

void grayscale(const cv::Mat& img, cv::Mat& res) {
    cv::cvtColor(img, res, cv::COLOR_BGR2GRAY);
}

这个函数用于将彩色图像转换为灰度图像。它接受输入图像 img 和输出图像 res 作为参数。

使用 cv::cvtColor 函数将输入图像从 BGR 颜色空间转换为灰度颜色空间,得到输出图像 res

6. 边缘检测

void edge_detection(const cv::Mat& img, cv::Mat& res) {
    cv::Canny(img, res, 100, 200);
}

这个函数用于进行边缘检测。它接受输入图像 img 和输出图像 res 作为参数。

使用 cv::Canny 函数对输入图像进行边缘检测,该函数接受输入图像、输出图像、低阈值和高阈值作为参数。边缘检测算法会根据像素的梯度强度来确定是否为边缘像素,如果像素的梯度强度大于高阈值,则被认为是边缘像素;如果像素的梯度强度小于低阈值,则被认为不是边缘像素;如果像素的梯度强度在低阈值和高阈值之间,则根据其与边缘像素的连接情况来确定是否为边缘像素。

7. 高斯模糊

void gaussian_blur(const cv::Mat& img, cv::Mat& res) {
    cv::GaussianBlur(img, res, cv::Size(5, 5), 0);
}

这个函数用于对图像进行高斯模糊处理。它接受输入图像 img 和输出图像 res 作为参数。

使用 cv::GaussianBlur 函数对输入图像进行高斯模糊,该函数接受输入图像、输出图像、模糊核大小和标准差作为参数。这里使用的模糊核大小为 cv::Size(5, 5),标准差为 0,表示由函数自动计算标准差。

8. 图像锐化

void sharpen(const cv::Mat& img, cv::Mat& res) {
    cv::Mat kernel = (cv::Mat_<float>(3, 3) <<
        0, -1, 0,
        -1, 5, -1,
        0, -1, 0);
    cv::filter2D(img, res, img.depth(), kernel);
}

这个函数用于对图像进行锐化处理。它接受输入图像 img 和输出图像 res 作为参数。

首先,定义一个 3x3 的锐化内核 kernel。然后,使用 cv::filter2D 函数对输入图像进行卷积操作,该函数接受输入图像、输出图像、图像深度和卷积内核作为参数。这里将输入图像与锐化内核进行卷积,得到输出图像 res,从而实现图像锐化的效果。

9. 颜色反转

void invert_colors(const cv::Mat& img, cv::Mat& res) {
    cv::bitwise_not(img, res);
}

这个函数用于对图像进行颜色反转处理。它接受输入图像 img 和输出图像 res 作为参数。

使用 cv::bitwise_not 函数对输入图像进行按位取反操作,即将每个像素的颜色值取反,得到输出图像 res

四、主函数实现

int main() {
    cv::Mat img = cv::imread("E:/pro/sdl_code/res/test_img.png");

    if (img.empty()) {
        std::cerr << "Error: Image not found." << std::endl;
        return -1;
    }

    cv::Mat sine_wave_img, cosine_wave_img, triangle_wave_img, sawtooth_wave_img, scale_img, rotate_img, gray_img, edge_img, blur_img, sharp_img, invert_img;

    // 不同波形效果
    wave(img, sine_wave_img, "sine", 20, 0.1);        // 正弦波
    wave(img, cosine_wave_img, "cosine", 20, 0.1);    // 余弦波
    wave(img, triangle_wave_img, "triangle", 20, 0.1); // 三角波
    wave(img, sawtooth_wave_img, "sawtooth", 20, 10); // 锯齿波

    // 缩放图像
    scale(img, scale_img, 0.5, 0.5);

    // 旋转图像
    rotate1(img, rotate_img, 45);

    // 颜色变换(灰度图)
    grayscale(img, gray_img);

    // 边缘检测
    edge_detection(img, edge_img);

    // 高斯模糊
    gaussian_blur(img, blur_img);

    // 图像锐化
    sharpen(img, sharp_img);

    // 颜色反转
    invert_colors(img, invert_img);

    // 显示所有效果
    cv::imshow("Original Image", img);
    cv::imshow("Sine Wave Effect", sine_wave_img);
    cv::imshow("Cosine Wave Effect", cosine_wave_img);
    cv::imshow("Triangle Wave Effect", triangle_wave_img);
    cv::imshow("Sawtooth Wave Effect", sawtooth_wave_img);
    cv::imshow("Scaled Image", scale_img);
    cv::imshow("Rotated Image", rotate_img);
    cv::imshow("Grayscale Image", gray_img);
    cv::imshow("Edge Detection", edge_img);
    cv::imshow("Gaussian Blur", blur_img);
    cv::imshow("Sharpened Image", sharp_img);
    cv::imshow("Inverted Colors", invert_img);

    cv::waitKey(0);

    // 保存结果图像
    //cv::imwrite("output_wave_image.jpg", wave_img);
    //cv::imwrite("output_scaled_image.jpg", scale_img);
    //cv::imwrite("output_rotated_image.jpg", rotate_img);
    //cv::imwrite("output_grayscale_image.jpg", gray_img);
    //cv::imwrite("output_edge_detection.jpg", edge_img);
    //cv::imwrite("output_gaussian_blur.jpg", blur_img);
    //cv::imwrite("output_sharpened_image.jpg", sharp_img);
    //cv::imwrite("output_inverted_colors.jpg", invert_img);

    return 0;
}

主函数首先读取输入图像,如果图像读取失败,则输出错误信息并返回 -1。然后,创建多个输出图像用于存储不同的处理效果。接下来,分别调用不同的函数对输入图像进行处理,得到各种效果的输出图像。最后,显示所有的图像,并等待用户按下任意键退出程序。如果需要保存结果图像,可以取消注释相应的代码行。

五、总结

本文介绍了如何使用 OpenCV 实现多种图像变换和处理效果,包括重映射图像创建波形效果、缩放图像、旋转图像、颜色变换、边缘检测、高斯模糊、图像锐化和颜色反转等。通过这些功能,我们可以对图像进行各种操作,从而实现不同的视觉效果。在实际应用中,可以根据具体需求选择合适的图像变换和处理方法,以达到更好的效果。

希望本文对大家学习和使用 OpenCV 有所帮助。如果有任何问题或建议,欢迎在评论区留言。首先介绍了 OpenCV 的重要性和本文要展示的内容。接着进行环境准备的说明,包括安装 OpenCV 和 C++编译器。然后对关键代码进行详细分析,分别解释了定义常量 M_PI、各种图像变换和处理函数的作用及实现原理。最后展示了主函数的实现,包括读取图像、创建输出图像、调用各种处理函数、显示图像和等待用户操作等。整体文章结构清晰,按照介绍、准备、分析、实现和总结的顺序进行撰写,以帮助读者更好地理解 OpenCV 的图像变换和处理功能。

到此这篇关于OpenCV图像变换与处理实战方法的文章就介绍到这了,更多相关OpenCV图像变换与处理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言链表实现学生信息管理系统程序设计

    C语言链表实现学生信息管理系统程序设计

    这篇文章主要为大家详细介绍了C语言链表实现学生信息管理系统程序设计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • C/C++ 判断计算机存储器字节序(端序)的几种方式

    C/C++ 判断计算机存储器字节序(端序)的几种方式

    字节序是计算机存储数据的格式,主存储器(主存)的字节序对程序的移植性和兼容性至关重要,利用联合体、指针、位移和掩码等方法可以检测和处理字节序问题,对于内存数据操作重要,也关系到跨平台和网络通信的数据处理
    2024-10-10
  • C语言float内存布局示例详解

    C语言float内存布局示例详解

    这篇文章主要为大家介绍了C语言float内存布局示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • 简单讲解哈希表

    简单讲解哈希表

    本文主要介绍了哈希表简单知识及C语言实现哈希表实例,文中利用图片以及代码简单讲解了相关知识,感兴趣的小伙伴可以多多学习这篇文章
    2021-09-09
  • c语言实现词频统计的简单实例

    c语言实现词频统计的简单实例

    下面小编就为大家带来一篇c语言实现词频统计的简单实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-09-09
  • C++中的策略模式浅析

    C++中的策略模式浅析

    策略模式属于C++设计模式中行为模式之一,该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。本文将通过示例详细讲解这一模式,需要的可以参考一下
    2023-02-02
  • C++ 中函数重载、覆盖与隐藏详解

    C++ 中函数重载、覆盖与隐藏详解

    这篇文章主要介绍了C++ 中函数重载、覆盖与隐藏详解的相关资料,需要的朋友可以参考下
    2017-05-05
  • STL区间成员函数及区间算法总结

    STL区间成员函数及区间算法总结

    这篇文章主要汇总介绍了STL区间成员函数及区间算法,有需要的小伙伴可以参考下。
    2015-07-07
  • 详解C++ 指针与二维数组名

    详解C++ 指针与二维数组名

    和一维数组类似,C++ 将二维数组名解释为其第一个元素的地址,而二维数组的第一个元素为一维数组,下面详细总结下二维数组名的性质,需要的朋友可以参考下
    2022-09-09
  • C++ 之 Asio 库(全面解析)

    C++ 之 Asio 库(全面解析)

    下面小编就为大家带来一篇C++ 之 Asio 库(全面解析)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08

最新评论