前言
在Android音视频开发中,网上知识点过于零碎,自学起来难度非常大,不过音视频大牛Jhuster提出了《Android 音视频从入门到提高 - 任务列表》,结合我自己的工作学习经历,我准备写一个音视频系列blog。本文是音视频系列blog的其中一个, 对应的要学习的内容是:使用OpenCV完成图片加载,图片腐蚀,图片模糊,图片边缘检测,图片保存。
音视频系列blog
音视频系列blog: 点击此处跳转查看
目录
1.1 效果展示
话不多说,先上效果图!(源代码在文章最后)
加载图片:
图片腐蚀:
图片模糊:
图片边缘检测:
1.2 图片加载
VS2017(或者其他版本VS)如何导入OpenCV,如果你不清楚,可以参考我的这篇文章:
OpenCV分析tfboys十周年演唱会灯牌大战结果
图片加载代码如下:
#include <opencv2/opencv.hpp>
#include <iostream>
// 加载图片
int main() {
// 定义图片文件的完整路径
std::string image_path = "D:\\path_to_your_image.jpg";
// 使用OpenCV加载图片
cv::Mat image = cv::imread(image_path);
if (image.empty()) {
std::cerr << "Error: Unable to load image." << std::endl;
return -1;
}
cv::imshow("Loaded Image", image);
cv::waitKey(0);
return 0;
}
Mat
在OpenCV中,cv::Mat
是一个非常重要的类,用于表示图像和矩阵数据,类似于Java中的 BufferedImage
类。它是OpenCV库中的核心数据结构之一,用于存储图像、矩阵和多维数组数据。cv::Mat
可以被看作是一个"容器",用来存储图像和矩阵数据,就像一个盒子,可以放入各种东西。
imread
imread
是 OpenCV 库中的一个函数,用于读取图像文件并将其加载到 cv::Mat
对象中。具体来说,imread
用于从磁盘上的图像文件读取像素数据,并将这些像素数据存储在 cv::Mat
中,以便后续的图像处理和分析。
在以下代码中:
cv::Mat image = cv::imread(image_path);
imread
将指定路径的图像文件加载到名为 image
的 cv::Mat
对象中。加载后,可以使用 image
对象进行图像处理操作。
imshow
imshow
也是 OpenCV 库中的一个函数,它用于显示图像在图形用户界面 (GUI) 窗口中,它允许你将图像在应用程序中的窗口中显示出来,以便用户可以看到图像的内容。
通常情况下,你可以将 cv::Mat
对象(包含加载的图像数据)传递给 imshow
函数,然后指定窗口的名称。例如:
cv::imshow("Loaded Image", image);
在这个示例中,"Loaded Image"
是窗口的名称,image
是包含图像数据的 cv::Mat
对象。当你调用 imshow
时,它将创建一个名为 "Loaded Image"
的窗口,并在该窗口中显示 image
中的图像数据。
waitKey(0)
cv::waitKey(0)
是 OpenCV 中的一个函数调用,它用于等待用户在图形用户界面 (GUI) 窗口中按下一个键。具体来说,这个函数在窗口上等待用户的键盘输入,并返回用户按下的键的ASCII码值。
在参数中的 0
表示函数将一直等待用户按键,直到用户按下键盘上的任意键。如果你将参数设置为一个正整数,例如 cv::waitKey(100)
,它将等待100毫秒,然后返回。如果用户在这个时间内按下了某个键,它将返回该键的ASCII码值;如果用户没有按下任何键,它将返回零。
通常,cv::waitKey
与 cv::imshow
一起使用,以便在显示图像时能够等待用户的交互。例如:
cv::imshow("Loaded Image", image);
int key = cv::waitKey(0);
if (key == 27) {
// 如果用户按下ESC键 (ASCII码值为27),则执行某些操作
// 比如关闭窗口。。。
}
在这个示例中,cv::waitKey
用于等待用户在显示图像窗口中按下任意键,并将按下的键的ASCII码值存储在变量 key
中。然后,您可以根据用户的输入执行不同的操作,例如根据按下的键来决定关闭窗口或执行其他处理。
1.3 图片腐蚀
要在OpenCV中对图像进行腐蚀操作,可以使用 cv::erode
函数。腐蚀是一种形态学操作,通常用于图像处理中的图像细化、去噪等任务。下面是一个示例,演示如何在OpenCV中执行图片腐蚀操作:
#include <opencv2/opencv.hpp>
#include <iostream>
int main() {
// 读取图像
cv::Mat image = cv::imread("D:\\path_to_your_image.jpg");
if (image.empty()) {
std::cerr << "Error: Unable to load image." << std::endl;
return -1;
}
// 创建一个核(用于定义腐蚀的形状和大小)
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5));
// 用来存放腐蚀之后的图片
cv::Mat erodedImage;
// 执行腐蚀操作
cv::erode(image, erodedImage, kernel);
// 显示原始图像和腐蚀后的图像
cv::imshow("原始图像", image);
cv::imshow("腐蚀后的图像", erodedImage);
// 等待用户按下键盘上的任意键
cv::waitKey(0);
return 0;
}
在这个示例中,我们首先读取了一张图像,然后创建了一个核(cv::Mat kernel
)来定义腐蚀操作的形状和大小。可以根据需要调整核的大小和形状。(这个核,包括下面的出现的两种核,如果不明白也没关系,我后面图像形态学会详细解释,你目前可以把这个核理解为一个工具,这个工具对每一个像素点进行相关操作,改变这个像素的数值,达到腐蚀,模糊等效果)
接下来,使用 cv::erode
函数来执行腐蚀操作,将原始图像 image
和核应用于腐蚀操作,结果存储在 erodedImage
中。
最后,我们使用 cv::imshow
来显示原始图像和腐蚀后的图像,然后使用 cv::waitKey
等待用户按下键盘上的任意键,以便查看结果。
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5));
这行代码创建了一个核(Kernel)用于形态学操作,特别是腐蚀操作。这行代码的含义:
cv::MORPH_RECT
:这是核的形状,表示矩形形状的核。形态学操作通常使用不同形状的核,例如矩形、椭圆或交叉形。在这里,我们选择了一个矩形形状的核,它将应用于腐蚀操作。cv::Size(5, 5)
:这是核的大小,表示核的宽度和高度。在这个示例中,我们创建了一个5x5大小的核,它是一个5列5行的矩阵,用于定义腐蚀的操作范围。核的大小会影响腐蚀的效果,较大的核会导致更强烈的腐蚀。
总之,这行代码创建了一个5x5大小的矩形核,它将用于执行腐蚀操作。腐蚀操作会在图像中移动这个核,将核与图像中的像素进行比较,并将核下的像素值设置为核中所有像素的最小值,从而导致图像中的边缘变细。核的大小和形状可以根据具体的应用和图像处理需求进行调整。
cv::erode(image, erodedImage, kernel);
这行代码使用了OpenCV的 cv::erode
函数来执行腐蚀操作。这行代码的含义:
image
:这是输入图像,即你希望对其执行腐蚀操作的图像。在这个示例中,image
包含了加载的原始图像数据。erodedImage
:这是输出图像,即腐蚀操作的结果将存储在erodedImage
中。cv::erode
函数将对输入图像image
执行腐蚀操作,并将结果存储在erodedImage
中。kernel
:这是先前创建的核(Kernel),它定义了腐蚀操作的形状和大小。腐蚀操作将使用这个核在输入图像上移动,将核下的像素值设置为核中所有像素的最小值,从而执行腐蚀。
1.4 图片模糊
要在OpenCV中对图像进行模糊操作,可以使用 cv::GaussianBlur
函数来执行高斯模糊。高斯模糊是一种常用的图像模糊方法,可以用于降低图像中的噪声或平滑图像。以下是一个示例代码,演示如何在OpenCV中执行高斯模糊:
#include <opencv2/opencv.hpp>
#include <iostream>
int main() {
// 读取图像
cv::Mat image = cv::imread("D:\\path_to_your_image.jpg");
if (image.empty()) {
std::cerr << "Error: Unable to load image." << std::endl;
return -1;
}
// 定义模糊核的大小
cv::Size kernelSize(5, 5); // 可以根据需要调整核的大小
// 用来存放模糊之后的图片
cv::Mat blurredImage;
// 执行高斯模糊操作
cv::GaussianBlur(image, blurredImage, kernelSize, 0);
// 显示原始图像和模糊后的图像
cv::imshow("Original Image", image);
cv::imshow("Blurred Image", blurredImage);
// 等待用户按下键盘上的任意键
cv::waitKey(0);
return 0;
}
在这个示例中,首先读取了一张图像,然后定义了模糊核的大小(kernelSize
)。
接下来,使用 cv::GaussianBlur
函数来执行高斯模糊操作,将原始图像 image
和模糊核应用于图像,结果存储在 blurredImage
中。
最后,我们使用 cv::imshow
来显示原始图像和模糊后的图像,并使用 cv::waitKey
等待用户按下键盘上的任意键,以便查看结果。
cv::Size kernelSize(5, 5);
cv::Size(5, 5)
是一个创建 OpenCV cv::Size
对象的语句,它用于指定模糊核的大小。它的含义:
cv::Size
是 OpenCV 中的一个类,用于表示大小或尺寸。它通常用于指定矩形、核、图像等的大小。(5, 5)
是一个包含两个整数的元组,表示宽度和高度。在这个示例中,(5, 5)
表示模糊核的宽度为5个像素,高度为5个像素,因此模糊核是一个5x5的矩形。
所以,cv::Size(5, 5)
的含义是创建一个大小为5x5的矩形核,该核将用于执行高斯模糊操作。核的大小会影响模糊的程度,较大的核会导致更强烈的模糊效果,而较小的核会产生更轻微的模糊效果。
高斯模糊是一种图像处理技术,用于降低图像中的噪声或平滑图像。它的主要原理是将图像中的每个像素点替换为其周围像素的加权平均值,其中权重是根据高斯分布来确定的。这意味着位于核中心的像素具有更大的权重,而离核中心越远的像素具有较小的权重。
高斯模糊的过程如下:
- 定义核的大小: 首先,需要定义一个模糊核,它是一个矩形或正方形的区域,大小由你自己指定。这个核的大小决定了模糊的程度。
- 遍历图像: 对于图像中的每个像素,将模糊核放置在该像素周围的区域。
- 计算加权平均值: 计算核内所有像素的加权平均值。核中心的像素具有最高的权重,而离中心越远的像素权重越低。
- 替换像素值: 使用计算出的平均值替换原始像素的值。这个操作对图像中的每个像素都会执行,从而产生模糊后的图像。
高斯模糊的主要效果是降低图像中的噪声,平滑细节,并模糊图像的轮廓。模糊核的大小决定了模糊的程度,较大的核会导致更强烈的模糊效果,而较小的核会产生较轻微的模糊效果。
cv::GaussianBlur(image, blurredImage, kernelSize, 0);
cv::GaussianBlur
是 OpenCV 中用于执行高斯模糊操作的函数。
image
:这是输入图像,即要对其执行高斯模糊操作的图像。在这个示例中,image
包含了加载的原始图像数据。blurredImage
:这是输出图像,即高斯模糊操作的结果将存储在blurredImage
中。cv::GaussianBlur
函数将对输入图像image
执行高斯模糊操作,并将结果存储在blurredImage
中。kernelSize
:这是一个cv::Size
对象,表示高斯核的大小。在之前的代码中定义了kernelSize
,它决定了高斯模糊的程度,即核的大小。在这个示例中,kernelSize
是一个5x5的大小,用于定义高斯核的大小。0
:这是高斯模糊的标准差(standard deviation),通常为零。标准差用于确定高斯分布的形状,它可以影响模糊的程度。在这里,将标准差设置为零表示使用默认值,而不自定义高斯分布的形状。
1.5 图片边缘检测
要在OpenCV中对图像进行边缘检测,可以使用一种称为Canny边缘检测的算法。以下是一个示例代码,演示如何在OpenCV中执行Canny边缘检测:
#include <opencv2/opencv.hpp>
#include <iostream>
int main() {
// 读取图像
cv::Mat image = cv::imread("D:\\path_to_your_image.jpg");
if (image.empty()) {
std::cerr << "Error: Unable to load image." << std::endl;
return -1;
}
// 用来存放边缘检测之后的图片
cv::Mat edges;
// 执行Canny边缘检测
cv::Canny(image, edges, 100, 200); // 调整阈值以控制边缘检测的灵敏度
// 显示原始图像和边缘检测结果
cv::imshow("Original Image", image);
cv::imshow("Edges", edges);
// 等待用户按下键盘上的任意键
cv::waitKey(0);
return 0;
}
在这个示例中,我们首先读取了一张图像。然后,我们使用 cv::Canny
函数来执行Canny边缘检测,将输入图像 image
和一些参数传递给它。在这里,参数 100
和 200
分别表示低阈值和高阈值。可以根据需要调整这些阈值以控制边缘检测的灵敏度。
最后,我们使用 cv::imshow
来显示原始图像和边缘检测的结果,并使用 cv::waitKey
等待用户按下键盘上的任意键,以便查看结果。
cv::Canny(image, edges, 100, 200);
cv::Canny
是 OpenCV 中用于执行Canny边缘检测的函数。
image
:这是输入图像,即要对其执行Canny边缘检测的图像。在这个示例中,image
包含了你加载的原始图像数据。请注意,Canny边缘检测通常用于灰度图像,因此在使用前,您可能需要将图像转换为灰度图像。edges
:这是输出图像,Canny边缘检测的结果将存储在edges
中。cv::Canny
函数将检测到的边缘信息存储在这个图像中。100
和200
:这是两个阈值参数。这两个阈值参数用于控制边缘检测的灵敏度和边缘连接的强度。100
是低阈值(Low threshold):低于这个阈值的边缘被丢弃(就是图片黑色部分)。200
是高阈值(High threshold):高于这个阈值的像素被认为是强边缘(就是图片白色部分)。
通过调整这两个阈值参数,可以控制Canny边缘检测的结果,以适应不同的图像和应用场景。较低的阈值会导致更多的边缘被检测到,而较高的阈值会产生更强的边缘。可以根据你的需求和图像特性来调整这些阈值。
1.6 图片保存
以下是一个示例代码,演示如何在OpenCV中对一张彩色图像执行Canny边缘检测,并将结果保存到D盘:
#include <opencv2/opencv.hpp>
#include <iostream>
int main() {
// 读取彩色图像
cv::Mat image = cv::imread("D:\\path_to_your_image.jpg");
if (image.empty()) {
std::cerr << "Error: Unable to load image." << std::endl;
return -1;
}
// 用来存放边缘检测之后的图片
cv::Mat edges;
// 执行Canny边缘检测
cv::Canny(image, edges, 100, 200); // 调整阈值以控制边缘检测的灵敏度
// 保存边缘检测结果到D盘
cv::imwrite("D:\\edges.jpg", edges);
std::cout << "Edges saved to D:\\edges.jpg" << std::endl;
return 0;
}
在这个示例中,我们首先读取了一张彩色图像,然后使用 cv::Canny
函数执行Canny边缘检测,将输入图像 image
作为输入,并将边缘检测结果存储在 edges
中。
接下来,我们使用 cv::imwrite
函数将边缘检测结果保存为一张新的图像文件,存储在D盘的根目录下,文件名为 “edges.jpg”。您可以根据需要更改保存路径和文件名。
cv::imwrite(“D:\edges.jpg”, edges);
cv::imwrite
是 OpenCV 中用于将图像保存为文件的函数。
"D:\\edges.jpg"
:这是保存图像的目标文件路径。在这里,图像将保存为名为 “edges.jpg” 的文件,该文件将存储在D盘(D:\)的根目录下。可以根据需要更改目标文件的路径和文件名。edges
:这是要保存的图像数据。在这个示例中,edges
包含了之前执行Canny边缘检测操作后得到的边缘图像数据。cv::imwrite
将这个图像数据保存为指定路径的图像文件。
源代码:(欢迎star)
OpenCV基础(一):图片加载,图片腐蚀,图片模糊,图片边缘检测,图片保存