在 OpenCV 中,图像分割是一个常见的操作,可以通过多种方法实现。以下是几种常用的图像分割技术示例,包括基于阈值的方法、轮廓检测和使用 K-means 聚类进行分割。
示例 1:基于阈值的图像分割
这是最简单且常用的图像分割方法之一。
#include <opencv2/opencv.hpp>
#include <iostream>
int main() {
// 读取图像
cv::Mat image = cv::imread("path_to_image.jpg");
if (image.empty()) {
std::cerr << "Error: Unable to load image!" << std::endl;
return -1;
}
// 转换为灰度图
cv::Mat gray;
cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);
// 应用阈值
cv::Mat binary;
double thresh = 128; // 阈值
cv::threshold(gray, binary, thresh, 255, cv::THRESH_BINARY);
// 显示结果
cv::imshow("Original Image", image);
cv::imshow("Binary Image", binary);
cv::waitKey(0);
return 0;
}
示例 2:轮廓检测
通过找到物体的边缘并提取轮廓来进行分割。
#include <opencv2/opencv.hpp>
#include <iostream>
int main() {
// 读取图像
cv::Mat image = cv::imread("path_to_image.jpg");
if (image.empty()) {
std::cerr << "Error: Unable to load image!" << std::endl;
return -1;
}
// 转换为灰度图并应用高斯模糊
cv::Mat gray, blurred;
cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);
cv::GaussianBlur(gray, blurred, cv::Size(5, 5), 0);
// 应用Canny边缘检测
cv::Mat edges;
cv::Canny(blurred, edges, 50, 150);
// 找到轮廓
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(edges.clone(), contours, hierarchy,
cv::RETR_EXTERNAL ,cv ::CHAIN_APPROX_SIMPLE );
// 在原始图上绘制轮廓
for (size_t i = 0; i < contours.size(); i++) {
drawContours(image, contours, static_cast<int>(i),
CV_RGB(0,255 ,0), 2);
}
// 显示结果
imshow("Contours", image);
waitKey(0);
return 0;
}
示例 3:K-means 聚类
使用 K-means 算法进行颜色空间的聚类以实现图像分割。
#include <opencv2/opencv.hpp>
#include <iostream>
int main() {
// 读取图像
cv :: Mat image =cv :: imread ("path_to_image.jpg");
if (image.empty()) {
std :: cerr <<"Error: Unable to load image!"<<std :: endl ;
return-1 ;
}
// 将数据转换为适合K-means算法格式,即二维矩阵(每个点都有三通道)
cv :: Mat data =image.reshape (1,image.total());
data.convertTo(data,CV_32F);
// 定义K-means参数
int K=3;
cv :: Mat labels ;
cv :: Mat centers ;
cv :: kmeans(data,K ,labels,
{cv :: TermCriteria(cv :: TERM_CRITERIA_EPS +cv ::
TERM_CRITERIA_MAX_ITER ,10 ,1.0),
KMEANS_RANDOM_CENTERS},10 ,centers);
// 重构分割后的图像
for(int i=0;i<data.rows ;i++)
data.at<float>(i)=(centers.at<float>(labels.at<int>(i),0)+centers.at<float>(labels.at<int>(i),1)+centers.at<float>(labels.at<int>(i),2))/3;
image=data.reshape (3,image.rows );
image.convertTo(image,CV_8UC3);
imshow ("K-Means Segmentation",image );
waitKey (0);
return(0);
}
编译与运行:
确保你已经安装了 OpenCV,并正确设置了编译环境。可以使用 g++ 或其他 C++ 编译器编译这些代码。例如:
g++ -o segmentation_example your_code.cpp `pkg-config --cflags --libs opencv4`
请根据你的系统和 OpenCV 安装情况调整命令。如果想要运行某个特定示例,请将相关代码放入同一文件中或按需创建多个文件。然后,替换 "path_to_image.jpg"
为实际的图片路径,以便程序能正常读取该文件。
内容由零声教学AI助手提供,问题来源于学员提问