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_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 的图像变换和处理功能。