摘要本文旨在为计算机视觉初学者提供一份详尽的OpenCV入门指南。从OpenCV的安装配置、依赖项安装,到基本语法和常用方法的解析,我们力求以通俗易懂的方式,配合丰富的代码示例,帮助读者快速掌握OpenCV的核心概念和技术,并为后续深入学习打下坚实的基础。无论您是Python爱好者还是C++开发者,都能从中受益。最后,欢迎大家加我的微信一起交流学习!
引言大家好!作为一名默语博主,我深知初学者在接触新技术时常常会感到迷茫。计算机视觉领域更是如此,涉及众多的概念和工具。今天,我就为大家带来一篇保姆级的OpenCV入门教程。OpenCV(Open Source Computer Vision Library)作为一个功能强大的开源计算机视觉库,是进行图像处理、视频分析、物体识别等任务的利器。别看它名字听起来很“高大上”,其实只要跟着我的步骤一步步来,你会发现它并没有想象中那么难。让我们一起开启OpenCV的奇妙之旅吧!
2. 环境准备在开始安装OpenCV之前,我们需要确保你的计算机满足一些基本条件,并安装必要的依赖项。
2.1 系统需求OpenCV支持多种操作系统,包括Windows、Linux、macOS等。你需要一台能够运行这些操作系统的计算机。对于初学者来说,Windows或Linux都是不错的选择。
2.2 安装依赖根据你选择的编程语言(Python或C++),需要安装相应的依赖库。
2.2.1 Python 环境如果你选择使用Python进行OpenCV开发,你需要确保已经安装了Python环境。建议安装Python 3.7或更高版本。
可以通过以下方式检查Python是否已安装以及版本:
Bash
代码语言:javascript代码运行次数:0运行复制python --version或者Bash
代码语言:javascript代码运行次数:0运行复制python3 --version如果尚未安装,请前往Python官方网站下载并安装。
接下来,我们需要安装一些Python的常用库,这些库能够帮助我们更好地使用OpenCV:
NumPy: OpenCV中的图像数据是以NumPy数组的形式存储的,因此NumPy是OpenCV的基础。Matplotlib: 用于绘制图像和图表。可以使用pip(Python的包管理器)来安装这些库:
Bash
代码语言:javascript代码运行次数:0运行复制pip install numpy matplotlib如果你的Python环境配置了多个版本,可能需要使用pip3命令:
Bash
代码语言:javascript代码运行次数:0运行复制pip3 install numpy matplotlib2.2.2 C++ 环境如果你选择使用C++进行OpenCV开发,你需要一个C++编译器。常用的编译器有:
Windows: MinGW-w64(通常与CMake结合使用)、Visual StudioLinux: GCC、ClangmacOS: Xcode此外,我们还需要安装CMake,它是一个跨平台的构建系统,用于管理OpenCV的编译过程。
Windows: 可以从CMake官方网站下载安装程序。
Linux (Debian/Ubuntu): 可以使用apt命令安装:
Bash
代码语言:javascript代码运行次数:0运行复制sudo apt update
sudo apt install cmake cmake-curses-guiLinux (Fedora/CentOS): 可以使用yum或dnf命令安装:
Bash
代码语言:javascript代码运行次数:0运行复制sudo yum install cmake cmake-gui或者
Bash
代码语言:javascript代码运行次数:0运行复制sudo dnf install cmake cmake-guimacOS: 可以使用Homebrew安装:
Bash
代码语言:javascript代码运行次数:0运行复制brew install cmake3. OpenCV安装接下来,我们将分别介绍Python和C++环境下OpenCV的安装方法。
3.1 Python 环境安装在Python环境下安装OpenCV非常简单,可以直接使用pip命令:
Bash
代码语言:javascript代码运行次数:0运行复制pip install opencv-python或者,如果你需要包含contrib模块(包含一些额外的、可能不太稳定的功能),可以使用以下命令:
Bash
代码语言:javascript代码运行次数:0运行复制pip install opencv-contrib-python同样地,如果你的Python环境配置了多个版本,可能需要使用pip3命令:
Bash
代码语言:javascript代码运行次数:0运行复制pip3 install opencv-python安装完成后,你可以在Python交互式环境中导入cv2模块来验证是否安装成功:
Python
代码语言:javascript代码运行次数:0运行复制import cv2
print(cv2.__version__)如果能够成功打印出OpenCV的版本号,则说明安装成功。
3.2 C++ 环境安装(源码编译)在C++环境下安装OpenCV通常需要从源码进行编译,这可能稍微复杂一些,但能够提供更大的灵活性。
3.2.1 下载OpenCV源码你可以从OpenCV官方GitHub仓库下载最新或指定版本的源码。通常会下载一个zip或tar.gz压缩包。
3.2.2 下载OpenCV Contrib模块(可选)如果你需要使用contrib模块中的额外功能,也需要从OpenCV Contrib GitHub仓库下载源码。
3.2.3 创建构建目录在OpenCV源码目录下创建一个名为build的文件夹,用于存放编译生成的文件。
Bash
代码语言:javascript代码运行次数:0运行复制mkdir build
cd build3.2.4 使用CMake配置在build目录下运行CMake,配置编译选项。你需要指定OpenCV源码的路径以及contrib模块的路径(如果下载了的话)。
Bash
代码语言:javascript代码运行次数:0运行复制cmake -D CMAKE_BUILD_TYPE=Release \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D INSTALL_C_EXAMPLES=OFF \
-D INSTALL_PYTHON_EXAMPLES=OFF \
-D BUILD_EXAMPLES=OFF \
-D WITH_QT=OFF \
-D WITH_OPENGL=OFF \
-D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules ../../opencv-D CMAKE_BUILD_TYPE=Release: 设置编译类型为Release,生成优化过的可执行文件。
-D CMAKE_INSTALL_PREFIX=/usr/local: 设置OpenCV的安装路径。你可以根据自己的需求修改。
-D INSTALL_C_EXAMPLES=OFF、
-D INSTALL_PYTHON_EXAMPLES=OFF、
-D BUILD_EXAMPLES=OFF 、 -D WITH_QT=OFF、
-D WITH_OPENGL=OFF
: 关闭一些不需要的选项,加快编译速度。
-D OPENCV_EXTRA_MODULES_PATH=…/…/opencv_contrib/modules 指定contrib模块的路径(相对于build目录)。你需要将其替换为你的实际路径。 …/…/opencv: 指定OpenCV源码的路径(相对于build目录)。同样需要根据你的实际路径进行调整。如果你没有下载contrib模块,可以省略-D OPENCV_EXTRA_MODULES_PATH=...这一行。
3.2.5 编译与安装配置完成后,使用make命令进行编译:
Bash
代码语言:javascript代码运行次数:0运行复制make -j4-j4表示使用4个线程进行编译,可以根据你的CPU核心数进行调整,加快编译速度。
编译完成后,使用以下命令进行安装:
Bash
代码语言:javascript代码运行次数:0运行复制sudo make install
sudo ldconfigsudo make install会将编译生成的文件安装到之前通过CMAKE_INSTALL_PREFIX指定的路径。sudo ldconfig会更新系统的动态链接库缓存,使得程序能够找到OpenCV的库文件。
4. OpenCV 配置安装完成后,我们还需要进行一些配置,以便在Python或C++项目中使用OpenCV。
4.1 Python 配置如果你是通过pip安装的OpenCV,通常情况下不需要进行额外的配置。Python会自动找到安装的cv2模块。
4.2 C++ 配置(CMake、IDE)如果你是通过源码编译安装的OpenCV,你需要告诉你的C++项目如何找到OpenCV的头文件和库文件。这通常通过CMake来实现。
4.2.1 使用CMakeLists.txt在你的C++项目的CMakeLists.txt文件中,你需要添加以下代码来查找OpenCV:
CMake
代码语言:javascript代码运行次数:0运行复制cmake_minimum_required(VERSION 3.10)
project(YourProjectName)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
link_directories(${OpenCV_LIBS})
add_executable(YourExecutableName main.cpp)
target_link_libraries(YourExecutableName ${OpenCV_LIBS}) ind_package(OpenCV REQUIRED): 告诉CMake查找OpenCV。如果找不到,会报错。
include_directories(${OpenCV_INCLUDE_DIRS}) : 将OpenCV的头文件目录添加到包含路径中。
link_directories(${OpenCV_LIBS}) : 将OpenCV的库文件目录添加到链接路径中(通常不需要显式指定, target_link_libraries会自动处理)。
target_link_libraries(YourExecutableName ${OpenCV_LIBS}): 将OpenCV的库文件链接到你的可执行文件。
4.2.2 在IDE中配置如果你使用集成开发环境(IDE)如Visual Studio或CLion,你需要配置项目的构建设置,告诉IDE OpenCV的头文件和库文件在哪里。
Visual Studio:
你需要在项目属性中的“VC++目录”->“包含目录”中添加OpenCV的头文件路径,并在“VC++目录”->“库目录”中添加OpenCV的库文件路径。然后在“链接器”->“输入”->“附加依赖项”中添加你需要链接的OpenCV库文件(例如opencv_world4xxx.lib,具体名称取决于你的OpenCV版本)。
CLion: CLion通常会使用你的CMakeLists.txt文件进行配置,所以只需要确保你的CMakeLists.txt文件配置正确即可。
5. 基本语法现在我们已经安装并配置好了OpenCV,接下来让我们学习一些基本的语法。
5.1 包含头文件与命名空间5.1.1 C++在使用OpenCV的C++代码中,你需要包含相应的头文件。通常会包含opencv2/opencv.hpp这个头文件,它包含了OpenCV的大部分常用模块。
C++
代码语言:javascript代码运行次数:0运行复制#include
int main() {
// OpenCV 代码
return 0;
}为了方便使用OpenCV的函数和类,可以添加命名空间:
C++
代码语言:javascript代码运行次数:0运行复制#include
using namespace cv;
int main() {
// 使用 cv::Mat 等
Mat image;
return 0;
}5.1.2 Python在使用OpenCV的Python代码中,你需要导入cv2模块:
Python
代码语言:javascript代码运行次数:0运行复制import cv2
# OpenCV 代码5.2 Mat 类详解cv::Mat(C++)或 numpy.ndarray(Python)是OpenCV中用于表示图像的核心数据结构。它可以表示单通道或多通道的图像,每个通道可以存储不同数据类型的像素值。
C++: cv::Mat是一个类,提供了丰富的方法来操作图像数据。你可以指定图像的尺寸、数据类型和通道数来创建Mat对象。
C++
代码语言:javascript代码运行次数:0运行复制// 创建一个3通道(BGR)、8位无符号整数类型的300x400的图像
Mat image(300, 400, CV_8UC3); CV_8U : 8位无符号整数(通常用于像素值,范围0-255)
C3 : 3通道(例如,BGR颜色图像)
Python: 在Python中,图像数据存储为NumPy数组。你可以使用NumPy的函数来创建和操作图像数组。
Python
代码语言:javascript代码运行次数:0运行复制import numpy as np
# 创建一个3通道的300x400的图像,像素值初始化为0
image = np.zeros((300, 400, 3), dtype=np.uint8) (300, 400, 3): 表示图像的形状(高度、宽度、通道数)
dtype=np.uint8: 表示数据类型为8位无符号整数
5.3 读取与显示图像5.3.1 C++可以使用cv::imread()函数读取图像,使用cv::imshow()函数显示图像,使用cv::waitKey()函数等待按键,使用cv::destroyAllWindows()函数关闭所有窗口。
C++
代码语言:javascript代码运行次数:0运行复制#include
using namespace cv;
int main() {
// 读取图像
Mat image = imread("path/to/your/image.jpg");
// 检查图像是否成功加载
if (image.empty()) {
std::cout << "Could not open or find the image" << std::endl;
return -1;
}
// 显示图像
imshow("Display window", image);
// 等待按键 (0表示无限等待)
waitKey(0);
// 关闭所有窗口
destroyAllWindows();
return 0;
}5.3.2 Python可以使用cv2.imread()函数读取图像,使用cv2.imshow()函数显示图像,使用cv2.waitKey()函数等待按键,使用cv2.destroyAllWindows()函数关闭所有窗口。
Python
代码语言:javascript代码运行次数:0运行复制import cv2
# 读取图像
img = cv2.imread('path/to/your/image.jpg')
# 检查图像是否成功加载
if img is None:
print("Could not open or find the image")
else:
# 显示图像
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()注意: 请将 "path/to/your/image.jpg" 替换为实际的图像文件路径。
5.4 视频读写5.4.1 C++可以使用cv::VideoCapture类读取视频或摄像头数据,使用cv::VideoWriter类写入视频。
读取视频:
C++
代码语言:javascript代码运行次数:0运行复制#include
using namespace cv;
int main() {
// 打开视频文件
VideoCapture cap("path/to/your/video.mp4");
// 检查视频是否成功打开
if (!cap.isOpened()) {
std::cout << "Could not open the video file" << std::endl;
return -1;
}
while (true) {
Mat frame;
// 从视频中读取一帧
cap >> frame;
// 如果没有更多帧,则退出循环
if (frame.empty())
break;
// 显示帧
imshow("Video Frame", frame);
// 等待按键 (延迟25毫秒)
if (waitKey(25) >= 0)
break;
}
// 释放 VideoCapture 对象
cap.release();
destroyAllWindows();
return 0;
}写入视频:
C++
代码语言:javascript代码运行次数:0运行复制#include
using namespace cv;
int main() {
// 获取视频的属性 (例如,宽度、高度、帧率) - 这里假设你知道这些属性
int frame_width = 640;
int frame_height = 480;
double fps = 30.0;
// 创建 VideoWriter 对象
VideoWriter writer("output.avi", VideoWriter::fourcc('M', 'J', 'P', 'G'), fps, Size(frame_width, frame_height));
// 检查 VideoWriter 对象是否成功创建
if (!writer.isOpened()) {
std::cout << "Could not open the output video file" << std::endl;
return -1;
}
// 创建一些帧并写入视频
for (int i = 0; i < 100; ++i) {
Mat frame(frame_height, frame_width, CV_8UC3, Scalar(i * 2, 255 - i * 2, 100));
writer.write(frame);
}
// 释放 VideoWriter 对象
writer.release();
return 0;
}5.4.2 Python可以使用cv2.VideoCapture()函数读取视频或摄像头数据,使用cv2.VideoWriter()函数写入视频。
读取视频:
Python
代码语言:javascript代码运行次数:0运行复制import cv2
# 打开视频文件
cap = cv2.VideoCapture('path/to/your/video.mp4')
# 检查视频是否成功打开
if not cap.isOpened():
print("Could not open the video file")
else:
while True:
ret, frame = cap.read()
# ret 是一个布尔值,表示是否成功读取到帧
# frame 是读取到的帧,如果成功读取则为图像数据,否则为 None
if not ret:
break
# 显示帧
cv2.imshow('Video Frame', frame)
# 等待按键 (延迟25毫秒)
if cv2.waitKey(25) & 0xFF == ord('q'):
break
# 释放 VideoCapture 对象
cap.release()
cv2.destroyAllWindows()写入视频:
Python
代码语言:javascript代码运行次数:0运行复制import cv2
# 获取视频的属性 (例如,宽度、高度、帧率) - 这里假设你知道这些属性
frame_width = 640
frame_height = 480
fps = 30.0
# 定义编码器和创建 VideoWriter 对象
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
out = cv2.VideoWriter('output.avi', fourcc, fps, (frame_width, frame_height))
# 创建一些帧并写入视频
for i in range(100):
frame = np.zeros((frame_height, frame_width, 3), dtype=np.uint8)
frame[:] = [i * 2, 255 - i * 2, 100] # 设置颜色
out.write(frame)
# 释放 VideoWriter 对象
out.release()
cv2.destroyAllWindows()6. 常用方法详解接下来,我们将介绍一些OpenCV中常用的图像处理方法。
6.1 色彩空间转换OpenCV提供了多种色彩空间之间的转换功能,例如BGR(Blue, Green, Red)到灰度图、HSV(Hue, Saturation, Value)等。
6.1.1 C++使用cv::cvtColor()函数进行色彩空间转换。
C++
代码语言:javascript代码运行次数:0运行复制#include
using namespace cv;
int main() {
Mat image = imread("path/to/your/image.jpg");
if (image.empty()) return -1;
// 转换为灰度图
Mat gray_image;
cvtColor(image, gray_image, COLOR_BGR2GRAY);
imshow("Original Image", image);
imshow("Gray Image", gray_image);
waitKey(0);
destroyAllWindows();
// 转换为HSV色彩空间
Mat hsv_image;
cvtColor(image, hsv_image, COLOR_BGR2HSV);
imshow("HSV Image", hsv_image);
waitKey(0);
destroyAllWindows();
return 0;
}6.1.2 Python使用cv2.cvtColor()函数进行色彩空间转换。
代码语言:javascript代码运行次数:0运行复制import cv2
img = cv2.imread('path/to/your/image.jpg')
if img is None:
exit()
# 转换为灰度图
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('Original Image', img)
cv2.imshow('Gray Image', gray_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 转换为HSV色彩空间
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
cv2.imshow('HSV Image', hsv_img)
cv2.waitKey(0)
cv2.destroyAllWindows()常用的色彩空间转换代码包括:
COLOR_BGR2GRAY: BGR到灰度
COLOR_BGR2HSV : BGR到HSV
COLOR_GRAY2BGR : 灰度到BGR
COLOR_HSV2BGR : HSV到BGR
6.2 图像阈值处理阈值处理用于将图像像素值二值化,即将大于或小于某个阈值的像素设置为一个特定的值。
6.2.1 C++使用cv::threshold()函数进行阈值处理。
代码语言:javascript代码运行次数:0运行复制#include
using namespace cv;
int main() {
Mat gray_image = imread("path/to/your/image.jpg", IMREAD_GRAYSCALE);
if (gray_image.empty()) return -1;
Mat thresh_binary;
threshold(gray_image, thresh_binary, 127, 255, THRESH_BINARY);
imshow("Binary Threshold", thresh_binary);
Mat thresh_binary_inv;
threshold(gray_image, thresh_binary_inv, 127, 255, THRESH_BINARY_INV);
imshow("Binary Inverse Threshold", thresh_binary_inv);
waitKey(0);
destroyAllWindows();
return 0;
}6.2.2 Python使用cv2.threshold()函数进行阈值处理。
代码语言:javascript代码运行次数:0运行复制import cv2
gray_img = cv2.imread('path/to/your/image.jpg', cv2.IMREAD_GRAYSCALE)
if gray_img is None:
exit()
ret, thresh_binary = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY)
cv2.imshow('Binary Threshold', thresh_binary)
ret, thresh_binary_inv = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY_INV)
cv2.imshow('Binary Inverse Threshold', thresh_binary_inv)
cv2.waitKey(0)
cv2.destroyAllWindows()常见的阈值类型包括:
THRESH_BINARY : 如果像素值大于阈值,则设置为最大值(通常为255),否则设置为0。
THRESH_BINARY_INV : 与 THRESH_BINARY相反。
THRESH_TRUNC : 如果像素值大于阈值,则设置为阈值,否则保持不变。
THRESH_TOZERO: 如果像素值大于阈值,则保持不变,否则设置为0。
THRESH_TOZERO_INV: 与 THRESH_TOZERO相反。
6.3 滤波与平滑滤波和平滑操作用于减少图像中的噪声。
6.3.1 C++常用的滤波方法包括均值滤波、高斯滤波、中值滤波等。
均值滤波:
代码语言:javascript代码运行次数:0运行复制#include
using namespace cv;
int main() {
Mat image = imread("path/to/your/image.jpg");
if (image.empty()) return -1;
Mat blur_image;
blur(image, blur_image, Size(5, 5));
imshow("Original Image", image);
imshow("Blurred Image", blur_image);
waitKey(0);
destroyAllWindows();
return 0;
}高斯滤波:
代码语言:javascript代码运行次数:0运行复制#include
using namespace cv;
int main() {
Mat image = imread("path/to/your/image.jpg");
if (image.empty()) return -1;
Mat gaussian_blur_image;
GaussianBlur(image, gaussian_blur_image, Size(5, 5), 0);
imshow("Original Image", image);
imshow("Gaussian Blurred Image", gaussian_blur_image);
waitKey(0);
destroyAllWindows();
return 0;
}中值滤波:
代码语言:javascript代码运行次数:0运行复制#include
using namespace cv;
int main() {
Mat image = imread("path/to/your/image.jpg");
if (image.empty()) return -1;
Mat median_blur_image;
medianBlur(image, median_blur_image, 5);
imshow("Original Image", image);
imshow("Median Blurred Image", median_blur_image);
waitKey(0);
destroyAllWindows();
return 0;
}6.3.2 Python均值滤波:
代码语言:javascript代码运行次数:0运行复制import cv2
img = cv2.imread('path/to/your/image.jpg')
if img is None:
exit()
blur_img = cv2.blur(img, (5, 5))
cv2.imshow('Original Image', img)
cv2.imshow('Blurred Image', blur_img)
cv2.waitKey(0)
cv2.destroyAllWindows()高斯滤波:
代码语言:javascript代码运行次数:0运行复制import cv2
img = cv2.imread('path/to/your/image.jpg')
if img is None:
exit()
gaussian_blur_img = cv2.GaussianBlur(img, (5, 5), 0)
cv2.imshow('Original Image', img)
cv2.imshow('Gaussian Blurred Image', gaussian_blur_img)
cv2.waitKey(0)
cv2.destroyAllWindows()中值滤波:
代码语言:javascript代码运行次数:0运行复制import cv2
img = cv2.imread('path/to/your/image.jpg')
if img is None:
exit()
median_blur_img = cv2.medianBlur(img, 5)
cv2.imshow('Original Image', img)
cv2.imshow('Median Blurred Image', median_blur_img)
cv2.waitKey(0)
cv2.destroyAllWindows()6.4 边缘检测边缘检测用于识别图像中亮度变化剧烈的区域。常用的边缘检测算法包括Canny、Sobel、Laplacian等。
6.4.1 C++Canny边缘检测:
代码语言:javascript代码运行次数:0运行复制#include
using namespace cv;
int main() {
Mat gray_image = imread("path/to/your/image.jpg", IMREAD_GRAYSCALE);
if (gray_image.empty()) return -1;
Mat canny_edges;
Canny(gray_image, canny_edges, 30, 100);
imshow("Original Image", gray_image);
imshow("Canny Edges", canny_edges);
waitKey(0);
destroyAllWindows();
return 0;
}6.4.2 PythonCanny边缘检测:
代码语言:javascript代码运行次数:0运行复制import cv2
gray_img = cv2.imread('path/to/your/image.jpg', cv2.IMREAD_GRAYSCALE)
if gray_img is None:
exit()
edges = cv2.Canny(gray_img, 30, 100)
cv2.imshow('Original Image', gray_img)
cv2.imshow('Canny Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()6.5 形态学操作形态学操作是基于图像形状的一些基本操作,如腐蚀、膨胀、开运算、闭运算等,常用于去除噪声、分离物体、连接断裂的区域等。
6.5.1 C++代码语言:javascript代码运行次数:0运行复制#include
using namespace cv;
int main() {
Mat binary_image = imread("path/to/your/binary_image.png", IMREAD_GRAYSCALE);
if (binary_image.empty()) return -1;
// 定义结构元素
Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5));
// 膨胀
Mat dilated_image;
dilate(binary_image, dilated_image, kernel);
imshow("Dilated Image", dilated_image);
// 腐蚀
Mat eroded_image;
erode(binary_image, eroded_image, kernel);
imshow("Eroded Image", eroded_image);
waitKey(0);
destroyAllWindows();
return 0;
}6.5.2 Python代码语言:javascript代码运行次数:0运行复制import cv2
import numpy as np
binary_img = cv2.imread('path/to/your/binary_image.png', cv2.IMREAD_GRAYSCALE)
if binary_img is None:
exit()
# 定义结构元素
kernel = np.ones((5, 5), np.uint8)
# 膨胀
dilation = cv2.dilate(binary_img, kernel, iterations=1)
cv2.imshow('Dilated Image', dilation)
# 腐蚀
erosion = cv2.erode(binary_img, kernel, iterations=1)
cv2.imshow('Eroded Image', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()常用的形态学操作包括:
MORPH_ERODE: 腐蚀MORPH_DILATE : 膨胀MORPH_OPEN : 开运算(先腐蚀后膨胀)MORPH_CLOSE : 闭运算(先膨胀后腐蚀)6.6 轮廓检测轮廓检测用于找到图像中物体的边界。
6.6.1 C++代码语言:javascript代码运行次数:0运行复制#include
using namespace cv;
#include
int main() {
Mat binary_image = imread("path/to/your/binary_image.png", IMREAD_GRAYSCALE);
if (binary_image.empty()) return -1;
std::vector
std::vector
findContours(binary_image, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
Mat image_with_contours = Mat::zeros(binary_image.size(), CV_8UC3);
for (size_t i = 0; i < contours.size(); i++) {
drawContours(image_with_contours, contours, (int)i, Scalar(0, 0, 255), 2, LINE_8, hierarchy, 0);
}
imshow("Original Binary Image", binary_image);
imshow("Image with Contours", image_with_contours);
waitKey(0);
destroyAllWindows();
return 0;
}6.6.2 Python代码语言:javascript代码运行次数:0运行复制import cv2
binary_img = cv2.imread('path/to/your/binary_image.png', cv2.IMREAD_GRAYSCALE)
if binary_img is None:
exit()
contours, hierarchy = cv2.findContours(binary_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
image_with_contours = cv2.cvtColor(binary_img, cv2.COLOR_GRAY2BGR)
cv2.drawContours(image_with_contours, contours, -1, (0, 0, 255), 2)
cv2.imshow('Original Binary Image', binary_img)
cv2.imshow('Image with Contours', image_with_contours)
cv2.waitKey(0)
cv2.destroyAllWindows()6.7 几何变换几何变换包括图像的缩放、平移、旋转、仿射变换和透视变换等。
6.7.1 C++缩放:
代码语言:javascript代码运行次数:0运行复制#include
using namespace cv;
int main() {
Mat image = imread("path/to/your/image.jpg");
if (image.empty()) return -1;
Mat resized_image;
resize(image, resized_image, Size(), 2.0, 2.0, INTER_LINEAR); // 放大两倍
imshow("Original Image", image);
imshow("Resized Image", resized_image);
waitKey(0);
destroyAllWindows();
return 0;
}6.7.2 Python缩放:
代码语言:javascript代码运行次数:0运行复制import cv2
img = cv2.imread('path/to/your/image.jpg')
if img is None:
exit()
resized_img = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_LINEAR) # 放大两倍
cv2.imshow('Original Image', img)
cv2.imshow('Resized Image', resized_img)
cv2.waitKey(0)
cv2.destroyAllWindows()6.8 绘制函数OpenCV提供了一些用于在图像上绘制基本形状的函数,如直线、矩形、圆、文本等。
6.8.1 C++代码语言:javascript代码运行次数:0运行复制#include
using namespace cv;
int main() {
Mat image(300, 400, CV_8UC3, Scalar(255, 255, 255)); // 创建白色图像
// 绘制直线
line(image, Point(50, 50), Point(350, 250), Scalar(255, 0, 0), 3);
// 绘制矩形
rectangle(image, Point(100, 100), Point(300, 200), Scalar(0, 255, 0), 2);
// 绘制圆形
circle(image, Point(200, 150), 40, Scalar(0, 0, 255), -1); // -1 表示填充
// 绘制文本
putText(image, "Hello OpenCV", Point(50, 280), FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 0, 0), 2);
imshow("Drawing", image);
waitKey(0);
destroyAllWindows();
return 0;
}6.8.2 Python代码语言:javascript代码运行次数:0运行复制import cv2
import numpy as np
img = np.zeros((300, 400, 3), dtype=np.uint8) + 255 # 创建白色图像
# 绘制直线
cv2.line(img, (50, 50), (350, 250), (255, 0, 0), 3)
# 绘制矩形
cv2.rectangle(img, (100, 100), (300, 200), (0, 255, 0), 2)
# 绘制圆形
cv2.circle(img, (200, 150), 40, (0, 0, 255), -1) # -1 表示填充
# 绘制文本
cv2.putText(img, "Hello OpenCV", (50, 280), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)
cv2.imshow('Drawing', img)
cv2.waitKey(0)
cv2.destroyAllWindows()7. 进阶技巧在掌握了基本语法和常用方法后,你可以尝试一些更高级的技巧。
7.1 ROI 与模板匹配ROI (Region of Interest) 是图像中你感兴趣的区域,可以单独对这部分区域进行处理。模板匹配是在一个大图中搜索与给定模板图像最相似的区域。
7.2 特征检测(ORB/SIFT/SURF)特征检测算法用于提取图像中具有代表性的点(特征点),这些特征点在图像匹配、物体识别等任务中非常有用。常见的算法有ORB、SIFT、SURF等。
7.3 摄像头标定与透视变换摄像头标定是获取摄像头内外参数的过程,可以用于校正图像畸变。透视变换可以将图像从一个视角变换到另一个视角,常用于图像矫正和拼接。
由于篇幅有限,这些进阶技巧将在后续的文章中详细介绍。
8. 常见问题与解决方案导入cv2模块失败: 确保OpenCV已经成功安装,并且Python环境配置正确。尝试重新安装或检查Python路径。无法打开图像或视频: 检查文件路径是否正确,文件是否存在,以及文件格式是否受OpenCV支持。编译错误: 检查CMake配置是否正确,依赖库是否安装完整,以及编译命令是否正确。运行缓慢: 尝试优化代码,例如减小图像尺寸,使用更高效的算法等。对于C++,可以尝试Release模式编译。如果在学习过程中遇到其他问题,欢迎在评论区提问,或者加我的微信与我交流。
9. 总结与建议恭喜你!通过本文的学习,你已经对OpenCV的安装、配置、基本语法和常用方法有了初步的了解。计算机视觉是一个充满挑战和乐趣的领域,OpenCV作为强大的工具,将帮助你实现各种有趣的想法。
我的建议是:
多动手实践: 学习编程最好的方式就是不断练习,尝试用OpenCV处理不同的图像和视频。查阅官方文档: OpenCV的官方文档非常详细,遇到问题时可以查阅官方文档获取更深入的理解。参与社区交流: 积极参与OpenCV相关的论坛、社区,与其他开发者交流学习经验。持续学习: 计算机视觉技术发展迅速,保持学习的热情,不断探索新的知识和技术。10. 参考资料OpenCV官方网站OpenCV官方GitHub仓库OpenCV Contrib GitHub仓库NumPy官方网站Matplotlib官方网站其他相关的技术博客和教程