摘要
本文旨在为计算机视觉初学者提供一份详尽的OpenCV入门指南。从OpenCV的安装配置、依赖项安装,到基本语法和常用方法的解析,我们力求以通俗易懂的方式,配合丰富的代码示例,帮助读者快速掌握OpenCV的核心概念和技术,并为后续深入学习打下坚实的基础。无论您是Python爱好者还是C++开发者,都能从中受益。最后,欢迎大家加我的微信一起交流学习!
引言
大家好!作为一名默语博主,我深知初学者在接触新技术时常常会感到迷茫。计算机视觉领域更是如此,涉及众多的概念和工具。今天,我就为大家带来一篇保姆级的OpenCV入门教程。OpenCV(Open Source Computer Vision Library)作为一个功能强大的开源计算机视觉库,是进行图像处理、视频分析、物体识别等任务的利器。别看它名字听起来很“高大上”,其实只要跟着我的步骤一步步来,你会发现它并没有想象中那么难。让我们一起开启OpenCV的奇妙之旅吧!
博主 默语带您 Go to New World.
✍ 个人主页—— 默语 的博客👦🏻 优秀内容
《java 面试题大全》
《java 专栏》
《idea技术专区》
《spring boot 技术专区》
《MyBatis从入门到精通》
《23种设计模式》
《经典算法学习》
《spring 学习》
《MYSQL从入门到精通》数据库是开发者必会基础之一~
🍩惟余辈才疏学浅,临摹之作或有不妥之处,还请读者海涵指正。☕🍭
🪁 吾期望此文有资助于尔,即使粗浅难及深广,亦备添少许微薄之助。苟未尽善尽美,敬请批评指正,以资改进。!💻⌨
默语是谁?
大家好,我是 默语,别名默语博主,擅长的技术领域包括Java、运维和人工智能。我的技术背景扎实,涵盖了从后端开发到前端框架的各个方面,特别是在Java 性能优化、多线程编程、算法优化等领域有深厚造诣。
目前,我活跃在CSDN、掘金、阿里云和 51CTO等平台,全网拥有超过15万的粉丝,总阅读量超过1400 万。统一 IP 名称为 默语 或者 默语博主。我是 CSDN 博客专家、阿里云专家博主和掘金博客专家,曾获博客专家、优秀社区主理人等多项荣誉,并在 2023 年度博客之星评选中名列前 50。我还是 Java 高级工程师、自媒体博主,北京城市开发者社区的主理人,拥有丰富的项目开发经验和产品设计能力。希望通过我的分享,帮助大家更好地了解和使用各类技术产品,在不断的学习过程中,可以帮助到更多的人,结交更多的朋友.
我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。
默语:您的前沿技术领航员
👋 大家好,我是默语!
📱 全网搜索“默语”,即可纵览我在各大平台的知识足迹。📣 公众号“默语摸鱼”,每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技术进阶之路畅通无阻。
💬 微信端添加好友“Solitudemind”,与我直接交流,不管是项目瓶颈的求助,还是行业趋势的探讨,随时畅所欲言。
📅 最新动态:2025 年 5 月 11 日
快来加入技术社区,一起挖掘技术的无限潜能,携手迈向数字化新征程!
好的,请看下面这篇关于OpenCV的入门到精通的技术博客文章,希望对您有所帮助!
OpenCV从入门到精通:安装、配置、依赖、基本语法与常用方法详解
目录
- 引言
- 环境准备
- 2.1 系统需求
- 2.2 安装依赖
- OpenCV安装
- 3.1 Python 环境安装
- 3.2 C++ 环境安装(源码编译)
- OpenCV 配置
- 4.1 Python 配置
- 4.2 C++ 配置(CMake、IDE)
- 基本语法
- 5.1 包含头文件与命名空间
- 5.2 Mat 类详解
- 5.3 读取与显示图像
- 5.4 视频读写
- 常用方法详解
- 6.1 色彩空间转换
- 6.2 图像阈值处理
- 6.3 滤波与平滑
- 6.4 边缘检测
- 6.5 形态学操作
- 6.6 轮廓检测
- 6.7 几何变换
- 6.8 绘制函数
- 进阶技巧
- 7.1 ROI 与模板匹配
- 7.2 特征检测(ORB/SIFT/SURF)
- 7.3 摄像头标定与透视变换
- 常见问题与解决方案
- 总结与建议
- 参考资料
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
python --version
或者Bash
python3 --version
如果尚未安装,请前往Python官方网站下载并安装。
接下来,我们需要安装一些Python的常用库,这些库能够帮助我们更好地使用OpenCV:
- NumPy: OpenCV中的图像数据是以NumPy数组的形式存储的,因此NumPy是OpenCV的基础。
- Matplotlib: 用于绘制图像和图表。
可以使用pip(Python的包管理器)来安装这些库:
Bash
pip install numpy matplotlib
如果你的Python环境配置了多个版本,可能需要使用pip3
命令:
Bash
pip3 install numpy matplotlib
2.2.2 C++ 环境
如果你选择使用C++进行OpenCV开发,你需要一个C++编译器。常用的编译器有:
- Windows: MinGW-w64(通常与CMake结合使用)、Visual Studio
- Linux: GCC、Clang
- macOS: Xcode
此外,我们还需要安装CMake,它是一个跨平台的构建系统,用于管理OpenCV的编译过程。
-
Windows: 可以从CMake官方网站下载安装程序。
-
Linux (Debian/Ubuntu): 可以使用apt命令安装:
Bash
sudo apt update sudo apt install cmake cmake-curses-gui
-
Linux (Fedora/CentOS): 可以使用yum或dnf命令安装:
Bash
sudo yum install cmake cmake-gui
或者
Bash
sudo dnf install cmake cmake-gui
-
macOS: 可以使用Homebrew安装:
Bash
brew install cmake
3. OpenCV安装
接下来,我们将分别介绍Python和C++环境下OpenCV的安装方法。
3.1 Python 环境安装
在Python环境下安装OpenCV非常简单,可以直接使用pip命令:
Bash
pip install opencv-python
或者,如果你需要包含contrib模块(包含一些额外的、可能不太稳定的功能),可以使用以下命令:
Bash
pip install opencv-contrib-python
同样地,如果你的Python环境配置了多个版本,可能需要使用pip3
命令:
Bash
pip3 install opencv-python
安装完成后,你可以在Python交互式环境中导入cv2模块来验证是否安装成功:
Python
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
mkdir build
cd build
3.2.4 使用CMake配置
在build
目录下运行CMake,配置编译选项。你需要指定OpenCV源码的路径以及contrib模块的路径(如果下载了的话)。
Bash
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
make -j4
-j4
表示使用4个线程进行编译,可以根据你的CPU核心数进行调整,加快编译速度。
编译完成后,使用以下命令进行安装:
Bash
sudo make install
sudo ldconfig
sudo 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
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++
#include <opencv2/opencv.hpp>
int main() {
// OpenCV 代码
return 0;
}
为了方便使用OpenCV的函数和类,可以添加命名空间:
C++
#include <opencv2/opencv.hpp>
using namespace cv;
int main() {
// 使用 cv::Mat 等
Mat image;
return 0;
}
5.1.2 Python
在使用OpenCV的Python代码中,你需要导入cv2
模块:
Python
import cv2
# OpenCV 代码
5.2 Mat 类详解
cv::Mat
(C++)或 numpy.ndarray
(Python)是OpenCV中用于表示图像的核心数据结构。它可以表示单通道或多通道的图像,每个通道可以存储不同数据类型的像素值。
-
C++:
cv::Mat
是一个类,提供了丰富的方法来操作图像数据。你可以指定图像的尺寸、数据类型和通道数来创建Mat
对象。C++
// 创建一个3通道(BGR)、8位无符号整数类型的300x400的图像 Mat image(300, 400, CV_8UC3);
-
CV_8U : 8位无符号整数(通常用于像素值,范围0-255)
-
C3 : 3通道(例如,BGR颜色图像)
-
-
Python: 在Python中,图像数据存储为NumPy数组。你可以使用NumPy的函数来创建和操作图像数组。
Python
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++
#include <opencv2/opencv.hpp>
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
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++
#include <opencv2/opencv.hpp>
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++
#include <opencv2/opencv.hpp>
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
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
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++
#include <opencv2/opencv.hpp>
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()
函数进行色彩空间转换。
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()
函数进行阈值处理。
#include <opencv2/opencv.hpp>
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()
函数进行阈值处理。
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++
常用的滤波方法包括均值滤波、高斯滤波、中值滤波等。
均值滤波:
#include <opencv2/opencv.hpp>
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;
}
高斯滤波:
#include <opencv2/opencv.hpp>
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;
}
中值滤波:
#include <opencv2/opencv.hpp>
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
均值滤波:
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()
高斯滤波:
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()
中值滤波:
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边缘检测:
#include <opencv2/opencv.hpp>
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 Python
Canny边缘检测:
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++
#include <opencv2/opencv.hpp>
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
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++
#include <opencv2/opencv.hpp>
using namespace cv;
#include <vector>
int main() {
Mat binary_image = imread("path/to/your/binary_image.png", IMREAD_GRAYSCALE);
if (binary_image.empty()) return -1;
std::vector<std::vector<Point>> contours;
std::vector<Vec4i> hierarchy;
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
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++
缩放:
#include <opencv2/opencv.hpp>
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
缩放:
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++
#include <opencv2/opencv.hpp>
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
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。如果你在学习过程中有任何疑问或者想要进一步交流,欢迎加我的微信:[Solitudemind ]。期待与你一起探索更多有趣的计算机视觉应用!
如对本文内容有任何疑问、建议或意见,请联系作者,作者将尽力回复并改进📓;( 联系微信:Solitudemind )
点击下方名片,加入 IT 技术核心学习团队。一起探索科技的未来,共同成长。
为了让您拥有更好的交互体验,特将这行文字设置为可点击样式:点击下方名片,加入 IT
技术核心学习团队。一起探索科技的未来,共同成长。