OpenCV 图像变换与处理实战

ops/2024/12/15 3:47:59/

OpenCV快速通关

第一章:OpenCV 简介与环境搭建
第二章:OpenCV 图像基本操作
第三章:OpenCV 图像变换与处理实战


OpenCV 图像变换与处理实战

  • OpenCV快速通关
  • OpenCV 图像变换与处理实战
    • 一、OpenCV 基础与图像处理概览
    • 二、图像变换理论精析
    • 三、图像增强与特征提取理论
    • 三、实例分析
      • 1. 定义常量 `M_PI`
      • 2. 重映射图像创建波形效果
      • 3. 缩放图像
      • 4. 旋转图像
      • 5. 颜色变换(灰度图)
      • 6. 边缘检测
      • 7. 高斯模糊
      • 8. 图像锐化
      • 9. 颜色反转
    • 四、主函数实现
    • 五、总结


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_xsrc_y,分别用于存储重映射后的 x 和 y 坐标。然后,通过双层循环遍历输入图像的每个像素。对于每个像素,将 src_x 中的对应值设置为当前像素的 x 坐标,并根据 wave_type 的不同计算出波形的值 wave_value。最后,将 src_y 中的对应值设置为当前像素的 y 坐标加上波形值。

最后,使用 cv::remap 函数根据 src_xsrc_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 的图像变换和处理功能。


http://www.ppmy.cn/ops/141992.html

相关文章

K8S 部署 Nacos:构建云原生服务管理基石

K8S 部署 Nacos&#xff1a;构建云原生服务管理基石 一、引言 在当今云原生应用蓬勃发展的时代&#xff0c;Kubernetes&#xff08;K8S&#xff09;已成为容器编排的事实标准&#xff0c;而 Nacos 作为一款强大的服务发现与配置管理中心&#xff0c;二者的结合为构建高效、可…

LightningChart JS助力德国医疗设备商打造高精度肺功能诊断软件

项目背景&#xff1a; GANSHORN Medizin Electronic GmbH公司在德国开发、生产和销售肺功能诊断设备已有 40 多年历史&#xff0c;该公司专注于肺功能的可视化&#xff0c;其创新医疗技术通过开发先进的肺量测定测试、肺扩散分析和人体肺量测定测试解决方案取得了突破。GANSHO…

负载均衡oj项目:介绍

目录 项目介绍 项目演示 项目介绍 负载均衡oj是一个基于bs模式的项目。 用户使用浏览器向oj模块提交代码&#xff0c;oj模块会在所有在线的后端主机中选择一个负载情况最低的主机&#xff0c;将用户的代码提交给该主机&#xff0c;该主机进行编译运行&#xff0c;将结果返回…

scala的多维数组

创建多维数组 创建多维数组可以使用Array.ofDim方法&#xff0c;该方法接受一个或多个整数参数&#xff0c;分别代表每个维度的大小。 // 创建一个3x3的二维数组&#xff0c;类型为Int val matrix Array.ofDim[Int](3, 3)// 创建一个3x3x3的三维数组&#xff0c;类型为Doubl…

Matlab数字信号处理——C-PML一维弹性波方程的数值模拟与边界处理

1 简单介绍 在地震波传播的数值模拟中&#xff0c;精确处理边界条件一直是关键挑战之一。传统的有限差分和有限元方法常因波动在边界处的反射导致模拟精度下降。本文实现非分裂卷积完全匹配层&#xff08;Convolutional Perfectly Matched Layer, C-PML&#xff09;技术&#…

k8s的Pod反亲和性

针对对象为Pod&#xff0c;目的是实现&#xff0c;新建Pod和目标Pod不要调度到一起&#xff0c;不在同一个Node上 示例&#xff1a; rootk8s-master:/home/vagrant# cat pod.yaml apiVersion: v1 kind: Pod metadata:name: testpod01labels:app: myapp01env: test1 spec:cont…

QoS分类和标记

https://zhuanlan.zhihu.com/p/160937314 1111111 分类和标记是识别每个数据包优先级的过程。 这是QoS控制的第一步&#xff0c;应在源主机附近完成。 分组通常通过其分组报头来分类。下图指定的规则仔细检查了数据包头 &#xff1a; 下表列出了分类标准&#xff1a; 普通二…

第k个元素

题目 以尽量高的效率求出一个乱序数组中按数值顺序的第k个元素值 解法1 以arr{10,9,8,7,6,5,4,3,2,1},k4的情况举例: 先选择一个候选中值6&#xff0c;比它小的放在它的左边&#xff0c;比它大的放在它的右边&#xff0c;那么该候选中值的排名可以知道是6。那么第4个元素在左…