c++ 实现meanshift

article/2025/11/6 13:18:00

自己手动实现了meanshift,算是把之前还有些模糊的地方给搞清楚了,本来应该半天就可以的,结果高斯核函数计算权重那里弄错了,多花了好一阵子功夫才搞定。

原理

对于所有样本点中的一个点x,计算它的shift vector,沿着shift vector移动,然后再计算x在移动后的位置上的新shift vector,再移动,直到最后到达终点了才算完。然后对所有点都进行一次这样的操作。
如果不使用核函数的话,就要规定一个半径,然后根据半径内点的mean来计算shift vector;如果使用高斯核函数的话就不需要了,因为高斯核函数的效果就是让离得近的点权重大,离得远的点权重很小。

加载数据

用了和上篇kmeans相同的数据

void MeanShiftClass::LoadData(string data_path, vector<MeanShift>& dataset)
{float arr1[64];float arr2[64];int i = 0;ifstream myfile(data_path);if (!myfile) {cout << "Unable to open file";exit(1); // terminate with error  }else{char str[64] = { 0 };while (!myfile.eof()){myfile.getline(str, 64); //读取一行数据sscanf_s(str, "%f %f", &arr1[i], &arr2[i]);i++;}}MeanShift tmp;for (int j = 0; j < i; j++){tmp.pos.x = arr1[j];tmp.pos.y = arr2[j];tmp.res.x = arr1[j];tmp.res.y = arr2[j];dataset.push_back(tmp);}
}

均值漂移

对于样本点x,计算均值漂移向量一次,当漂移距离小于EPSILON时就停止,计算下一个点。

void MeanShiftClass::ShiftOnce(MeanShift& p)
{float x_sum = 0;float y_sum = 0;float weight_sum = 0;for (int i = 0; i < point_num; i++){float tmp_distance = GetEuclideanDistance(p.res, dataset[i].pos);float weight = GaussianKernel(tmp_distance, kernel_bandwidth);x_sum += dataset[i].pos.x * weight;y_sum += dataset[i].pos.y * weight;weight_sum += weight;}Point2f shift_vector(x_sum/ weight_sum, y_sum/ weight_sum);float shift_distance = GetEuclideanDistance(p.res, shift_vector);cout << "shift_distance = " << shift_distance << endl;if (shift_distance < EPSILON)stop = true;p.res = shift_vector;
}
void MeanShiftClass::DoMeanShiftCluster()
{for (int i = 0; i < point_num; i++){stop = false;while (!stop){Sleep(20);ShiftOnce(dataset[i]);}cout <<"("<< dataset[i].res.x << "," << dataset[i].res.y<<")" << endl;}LabelClusters();
}

给聚类结果打标签

聚完类之后给他们打上标签,聚类结果距离小于CLUSTER_EPSILON的点认为是一类。

void MeanShiftClass::LabelClusters()
{int current_label = -1;for (int i = 0; i < point_num; i++){if (dataset[i].label != -1)continue;current_label++;for (int j = 0; j < point_num; j++){if (GetEuclideanDistance(dataset[i].res, dataset[j].res) < CLUSTER_EPSILON){dataset[j].label = current_label;}}}
}

结果

这是聚类前的数据点
在这里插入图片描述
这是聚类结果
在这里插入图片描述
实现了对表盘上多位数字的合并,方便后续的处理。原始数据点是数字方框的位置坐标。

源码

MeanShiftClass.h

#pragma once
#include <iostream>
#include <opencv2/opencv.hpp>
#include <windows.h>
#define PI 3.1415926535898
#define EPSILON 0.001
#define CLUSTER_EPSILON 10using namespace cv;
using namespace std;struct MeanShift
{Point2f pos;Point2f res;int label = -1;
};class MeanShiftClass
{
public:MeanShiftClass(int _bandwidth);~MeanShiftClass();void DoMeanShiftCluster();
private:bool stop;int point_num;int cluster_num;int kernel_bandwidth;vector<MeanShift> dataset;void LabelClusters();void ShowClusterResult();void ShiftOnce(MeanShift& p);int GetManhattanDistance(Point2f p0, Point2f p1);float GaussianKernel(int distance, int bandwidth);float GetEuclideanDistance(Point2f p0, Point2f p1);void LoadData(string data_path, vector<MeanShift> &dataset);
};

MeanShiftClass.cpp

#include "pch.h"
#include "MeanShiftClass.h"MeanShiftClass::MeanShiftClass(int _bandwidth)
{LoadData("DigitDetcResult_vec2.txt", dataset);point_num = dataset.size();kernel_bandwidth = _bandwidth;stop = false;
}MeanShiftClass::~MeanShiftClass()
{
}void MeanShiftClass::DoMeanShiftCluster()
{for (int i = 0; i < point_num; i++){stop = false;while (!stop){Sleep(20);ShiftOnce(dataset[i]);}cout <<"("<< dataset[i].res.x << "," << dataset[i].res.y<<")" << endl;}LabelClusters();ShowClusterResult();
}void MeanShiftClass::ShowClusterResult()
{Mat src = imread("2.jpg");for (int i = 0; i < dataset.size(); i++){circle(src, dataset[i].pos, 3, Scalar(0, 0, 255), -1);}imshow("src", src);waitKey(0);
}void MeanShiftClass::LoadData(string data_path, vector<MeanShift>& dataset)
{float arr1[64];float arr2[64];int i = 0;ifstream myfile(data_path);if (!myfile) {cout << "Unable to open file";exit(1); // terminate with error  }else{char str[64] = { 0 };while (!myfile.eof()){myfile.getline(str, 64); //读取一行数据sscanf_s(str, "%f %f", &arr1[i], &arr2[i]);i++;}}MeanShift tmp;for (int j = 0; j < i; j++){tmp.pos.x = arr1[j];tmp.pos.y = arr2[j];tmp.res.x = arr1[j];tmp.res.y = arr2[j];dataset.push_back(tmp);}
}int MeanShiftClass::GetManhattanDistance(Point2f p0, Point2f p1)
{return abs(p0.x - p1.x) + abs(p0.y - p1.y);
}float MeanShiftClass::GetEuclideanDistance(Point2f p0, Point2f p1)
{return sqrt((p0.x - p1.x)*(p0.x - p1.x) + (p0.y - p1.y)*(p0.y - p1.y));
}float MeanShiftClass::GaussianKernel(int distance, int bandwidth)
{return exp(-0.5*(distance*distance) / (bandwidth*bandwidth));
}void MeanShiftClass::ShiftOnce(MeanShift& p)
{float x_sum = 0;float y_sum = 0;float weight_sum = 0;for (int i = 0; i < point_num; i++){float tmp_distance = GetEuclideanDistance(p.res, dataset[i].pos);float weight = GaussianKernel(tmp_distance, kernel_bandwidth);x_sum += dataset[i].pos.x * weight;y_sum += dataset[i].pos.y * weight;weight_sum += weight;}Point2f shift_vector(x_sum/ weight_sum, y_sum/ weight_sum);float shift_distance = GetEuclideanDistance(p.res, shift_vector);cout << "shift_distance = " << shift_distance << endl;if (shift_distance < EPSILON)stop = true;p.res = shift_vector;
}void MeanShiftClass::LabelClusters()
{int current_label = -1;for (int i = 0; i < point_num; i++){if (dataset[i].label != -1)continue;current_label++;for (int j = 0; j < point_num; j++){if (GetEuclideanDistance(dataset[i].res, dataset[j].res) < CLUSTER_EPSILON){dataset[j].label = current_label;}}}
}

记录一下~


http://chatgpt.dhexx.cn/article/qZqYeZ01.shtml

相关文章

Meanshift均值漂移聚类算法

一、meanshift 均值漂移就是把指定的样本点沿着密度上升的方向移向高密度区域。这里可以用矢量加法的几何意义来理解。参考博文Mean Shift 聚类算法 meanshift为 M r ( x ) 1 k ∑ x i ∈ S r ( x ) ( x i − x ) M_r(x)\frac{1}{k}\sum\limits_{x_i\in S_r(x)}(x_i-x) Mr​…

MeanShift 目标跟踪

MeanShift算法&#xff0c;又称为均值漂移算法&#xff0c;采用基于颜色特征的核密度估计&#xff0c;寻找局部最优&#xff0c;使得跟踪过程中对目标旋转&#xff0c;小范围遮挡不敏感。 文章目录 MeanShift 原理MeanShift 跟踪步骤meanShift 函数原型反向投影MeanShift 跟踪…

MeanShift跟踪MATLAB实现

一、简介 核跟踪方法是目标跟踪的主要方法, 应用非常广泛。例如Meashift、Camshift 算法, 它直接运用最速下降法的原理, 向梯度下降方向对目标模板逐步迭代, 直到迭代到最优位置。它的核心就是一步一步迭代寻找最优点, 在跟踪中, 就是为了寻找相似度值最大的候选区间。 本文主…

OpenCV每日函数 对象追踪模块 Meanshift算法

1、meanshift的基本思想 meanshift 背后的直觉很简单。考虑你有一组点。(它可以是像直方图反投影这样的像素分布)。您有一个小窗口(可能是一个圆圈),您必须将该窗口移动到最大像素密度(或最大点数)的区域。如下图所示: 2、meanshift的原理简述 均值偏移和模式发现技术,…

meanshift算法学习(二):opencv中的meanshift

0.前言 接着上一篇文章点击打开链接说&#xff0c;opencv中提供的meanshift可以用来实现跟踪&#xff0c;其基本原理是迭代求解概率分布的“局部极值”。这一篇内容&#xff0c;我只讲opencv中的meanshift的用法和源代码分析。因为&#xff1a;&#xff08;1&#xff09;具体的…

聚类算法之Mean Shift

Mean Shift聚类算法 1. 基本原理 对于Mean Shift算法&#xff0c;是一个迭代得步骤&#xff0c;即每次迭代的时候&#xff0c;都是找到圆里面点的平均位置作为新的圆心位置。说的简单一点&#xff0c;使得圆心一直往数据密集度最大的方向移动。 2. 基本的Mean Shift向量形式…

meanshift跟踪算法

以下是用meanshift实现目标跟踪的实验报告&#xff08;包含源码&#xff09;&#xff0c;实验中详细介绍了meanshift跟踪算法的原理&#xff0c;结合OTB100跟踪数据集对meanshift跟踪效果进行了分析。 目 录 一.实验名称 二.实验目的 三.实验原理 3.1 前言 3.2 meanshift …

传统目标跟踪——MeanShift算法

目录 一、均值漂移&#xff08;MeanShift&#xff09; 二、流程 三、代码 3.1 meanshift&#xff0b;固定框的代码 3.2 优化&#xff1a;meanshift鼠标选择 3.3 meanshift自己实现函数 四、补充知识 4.1 直方图 4.2 归一化 4.3 直方图反投影 一、均值漂移&#xff08;…

Mean Shift 聚类算法

原文&#xff1a;https://blog.csdn.net/hjimce/article/details/45718593 一、mean shift 算法理论 Mean shift 算法是基于核密度估计的爬山算法&#xff0c;可用于聚类、图像分割、跟踪等&#xff0c;因为最近搞一个项目&#xff0c;涉及到这个算法的图像聚类实现&#xff…

mean shift聚类matlab,机器学习:Mean Shift聚类算法

今天的文章介绍如何利用Mean Shift算法的基本形式对数据进行聚类操作。而有关Mean Shift算法加入核函数计算漂移向量部分的内容将不在本文讲述范围内。实际上除了聚类&#xff0c;Mean Shift算法还能用于计算机视觉等场合&#xff0c;有关该算法的理论知识请参考这篇文章。 Mea…

Python 实现MeanShift算法

原理 大家自行百度吧&#xff0c;我懒得码字了 推荐一下原理原理https://blog.csdn.net/jinshengtao/article/details/30258833 代码 直接上代码了&#xff0c;看不懂&#xff0c;就参照一下原理 # author: wdq # contact: 1920132572qq.com # datetime:2022/3/15 17:40 # …

Sklearn聚类算法之meanshift

以二维来说明可能更容易理解&#xff0c;下图中的很多的红点就是我们的样本特征点&#xff0c;meanshift就是在这些点中的任意一个点为圆心&#xff0c;然后以半径R画一个圆&#xff08;在opencv中是一个矩形&#xff09;&#xff0c;然后落在这个圆中的所有点和圆心都会对应的…

Python实现Mean Shift聚类算法

Mean Shift算法&#xff0c;又称均值聚类算法&#xff0c;聚类中心是通过在给定区域中的样本均值确定的&#xff0c;通过不断更新聚类中心&#xff0c;直到聚类中心不再改变为止&#xff0c;在聚类、图像平滑、分割和视频跟踪等方面有广泛的运用。 Mean Shift向量 对于给定的…

mean shift 跟踪算法

说明一&#xff1a; Mean Shift算法,一般是指一个迭代的步骤,即先算出当前点的偏移均值,移动该点到其偏移均值,然后以此为新的起始点,继续移动,直到满足一定的条件结束. 1. Meanshift推导 给定d维空间Rd的n个样本点 ,i1,…,n,在空间中任选一点x&#xff0c;那么Mean Shift向量…

Python实现Mean Shift算法

声明&#xff1a;代码的运行环境为Python3。Python3与Python2在一些细节上会有所不同&#xff0c;希望广大读者注意。本博客以代码为主&#xff0c;代码中会有详细的注释。相关文章将会发布在我的个人博客专栏《Python从入门到深度学习》&#xff0c;欢迎大家关注~ 在K-Means算…

meanshift算法 java_Meanshift,聚类算法

记得刚读研究生的时候&#xff0c;学习的第一个算法就是meanshift算法&#xff0c;所以一直记忆犹新&#xff0c;今天和大家分享一下Meanshift算法&#xff0c;如有错误&#xff0c;请在线交流。 Mean Shift算法,一般是指一个迭代的步骤,即先算出当前点的偏移均值,移动该点到其…

保边滤波之Mean shift filter

Mean shift filter 目录 Mean shift filter 一、算法原理 二、练手实现的算法代码如下&#xff1a; 三、实现结果 一、算法原理 在OpenCV中&#xff0c;meanshift filter函数为 pyrMeanShiftFiltering&#xff0c; 它的函数调用格式如下&#xff1a; C: void pyrMeanShif…

mean shift

参考&#xff1a; http://blog.csdn.net/google19890102/article/details/51030884 http://www.cvvision.cn/5778.html https://wenku.baidu.com/view/5862334827d3240c8447ef40.html http://blog.csdn.net/qq_23968185/article/details/51804574 https://www.cnblogs.com…

机器学习算法原理与实践(二)、meanshift算法图解以及在图像聚类、目标跟踪中的应用

【原创】Liu_LongPo 转载请注明出处 【CSDN】http://blog.csdn.net/llp1992 最近在关注跟踪这一块的算法&#xff0c;对于meanshift的了解也是来自论文和博客&#xff0c;本博客将对meanshift算法进行总结&#xff0c;包括meanshift算法原理以及公式推导&#xff0c;图解&…

基于MeanShift的目标跟踪算法及实现

这次将介绍基于MeanShift的目标跟踪算法&#xff0c;首先谈谈简介&#xff0c;然后给出算法实现流程&#xff0c;最后实现了一个单目标跟踪的MeanShift算法【matlab/c两个版本】 csdn贴公式比较烦&#xff0c;原谅我直接截图了… 一、简介 首先扯扯无参密度估计理论&#xff0c…