- 操作系统:ubuntu22.04
- OpenCV版本:OpenCV4.9
- IDE:Visual Studio Code
- 编程语言:C++11
算法描述
函数执行均值迁移图像分割的初始步骤。
该函数实现了均值迁移分割的过滤阶段,即输出是经过滤波的“海报化”图像,其中颜色梯度和平滑纹理已被平坦化。对于输入图像(或缩小的输入图像,见下文)的每一个像素 (X,Y),函数都会执行均值迁移迭代,也就是说,在联合空间-色彩超空间中考虑像素 (X,Y) 的邻域:
(
x
,
y
)
:
X
−
sp
≤
x
≤
X
+
sp
,
Y
−
sp
≤
y
≤
Y
+
sp
,
∣
∣
(
R
,
G
,
B
)
−
(
r
,
g
,
b
)
∣
∣
≤
sr
(x,y): X- \texttt{sp} \le x \le X+ \texttt{sp} , Y- \texttt{sp} \le y \le Y+ \texttt{sp} , ||(R,G,B)-(r,g,b)|| \le \texttt{sr}
(x,y):X−sp≤x≤X+sp,Y−sp≤y≤Y+sp,∣∣(R,G,B)−(r,g,b)∣∣≤sr
其中 (R,G,B) 和 (r,g,b) 分别是在 (X,Y) 和 (x,y) 上的颜色分量向量(尽管算法并不依赖于所使用的颜色空间,因此任何 3 组件颜色空间都可以使用)。在邻域内找到平均空间值 (X’,Y’) 和平均颜色向量 (R’,G’,B’),它们作为下一次迭代的邻域中心:
(
X
,
Y
)
(
X
′
,
Y
′
)
,
(
R
,
G
,
B
)
(
R
′
,
G
′
,
B
′
)
.
(X,Y)~(X',Y'), (R,G,B)~(R',G',B').
(X,Y) (X′,Y′),(R,G,B) (R′,G′,B′).
迭代完成后,初始像素(即迭代开始的像素)的颜色分量设置为最终值(最后一次迭代的平均颜色):
I
(
X
,
Y
)
<
−
(
R
∗
,
G
∗
,
B
∗
)
I(X,Y) <- (R*,G*,B*)
I(X,Y)<−(R∗,G∗,B∗)
当 maxLevel > 0 时,构建高斯金字塔,包含 maxLevel+1 层,并首先在最小层上运行上述过程。之后,结果传播到较大的层,并且仅在金字塔较低分辨率层的颜色与当前层的颜色相差超过 sr 的像素上再次运行迭代。这使得颜色区域的边界更加清晰。需要注意的是,结果实际上与在整个原始图像上运行均值迁移程序(即 maxLevel==0)的结果不同。
pyrMeanShiftFiltering 是 OpenCV 中的一个函数,用于实现均值迁移滤波(Mean Shift Filtering)。这是一种非局部均值滤波技术,可以用于图像分割、降噪等多种图像处理任务。
函数原型
void cv::pyrMeanShiftFiltering
(
InputArray src,
OutputArray dst,
double sp,
double sr,
int maxLevel = 1,
TermCriteria termcrit = TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 5, 1)
)
参数
- 参数src 源图像,8 位、3 通道。
- 参数dst 目标图像,与源图像格式和大小相同。
- 参数sp 空间窗口半径。
- 参数sr 颜色窗口半径。
- 参数maxLevel 用于分割的最大金字塔层级。
- 参数termcrit 终止准则:何时停止均值迁移迭代。
代码示例
#include <opencv2/opencv.hpp>
#include <iostream>
int main() {
// 加载图像
cv::Mat img = cv::imread("/media/dingxin/data/study/OpenCV/sources/images/erik.jpg", cv::IMREAD_COLOR);
if (img.empty()) {
std::cout << "无法加载图像,请检查路径是否正确。" << std::endl;
return -1;
}
cv::Size sz2Sh( 400, 600 );
cv::resize( img, img, sz2Sh, 0, 0, cv::INTER_LINEAR_EXACT );
// 使用 pyrMeanShiftFiltering 对图像进行滤波
cv::Mat filtered_img;
double spatial_radius = 10; // 空间窗口半径
double color_radius = 20; // 颜色窗口半径
int max_level = 1; // 最大金字塔层级
cv::TermCriteria term_crit(cv::TermCriteria::MAX_ITER+cv::TermCriteria::EPS, 5, 1); // 终止准则
cv::pyrMeanShiftFiltering(img, filtered_img, spatial_radius, color_radius, max_level, term_crit);
// 显示结果
cv::namedWindow("Original Image", cv::WINDOW_NORMAL);
cv::imshow("Original Image", img);
cv::namedWindow("Filtered Image", cv::WINDOW_NORMAL);
cv::imshow("Filtered Image", filtered_img);
cv::waitKey(0); // 等待按键
return 0;
}