我的编程空间,编程开发者的网络收藏夹
学习永远不晚

openCV中如何实现meanshift算法查找目标

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

openCV中如何实现meanshift算法查找目标

这篇文章将为大家详细讲解有关openCV中如何实现meanshift算法查找目标,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

    一、简介

    图像直方图的反向投影是一个概率分布图,表示一个指定图像片段出现在特定位置的概率。当我们已知图像中某个物体的大体位置时,可以通过概率分布图找到物体在另一张图像中的准确位置。我们可以设定一个初始位置,在其周围反复移动来提高局部匹配概率,从而找到物体的准确位置,这个实现过程叫做均值平移算法。

    二、实现过程

    因为人物的面部特征相对于其他位置更明显,本次实验主要应用于人物的面部识别。

    1、设定感兴趣的区域

    感兴趣区域的设定有两种方式,一种是已知图片人物脸部位置的像素坐标,通过设定矩形框来定位到人物脸部位置,另一种是使用opencv自带的selectROI函数,手动框选自己感兴趣的位置。

    openCV中如何实现meanshift算法查找目标

    2、获取脸部直方图并做归一化

    设置一个ColorHistogram类增加一个获取色调直方图的函数getHueHistogram。此函数包含将图像转换成HSV色彩空间,屏蔽低饱和度的像素(可能用到,也可能用不到),计算图像直方图。

    cv::Mat getHueHistogram(const cv::Mat &image2, int minSaturation = 0){cv::Mat hist; //转换成HSV色彩空间cv::Mat hsv;cv::cvtColor(image2, hsv, CV_BGR2HSV);//cv::imshow("hsv", hsv); //掩码(可能用的到也可能用不到)cv::Mat mask;if (minSaturation > 0) {std::vector<cv::Mat>v;cv::split(hsv, v);  //将3个通道分割进3幅图像 cv::threshold(v[1], mask, minSaturation, 255, cv::THRESH_BINARY);//屏蔽低饱和度的像素} //准备一维色调直方图的参数hranges[0] = 0.0;hranges[1] = 180.0;  //范围是0~180channels[0] = 0;   //色调通道 //计算直方图cv::calcHist(&hsv, 1,   //仅为一幅图像的直方图channels,             //使用的通道mask,                 //二值掩码hist,                 //作为结果的直方图1,                    //这是一维的直方图histSize,             //箱子数量ranges);              //像素值的范围return hist;}

    然后,对获取的直方图做归一化。

    void setHistogram(const cv::Mat& h) {histogram = h;cv::normalize(histogram, histogram, 1.0);}

    3、反向投影,用meanshift查找目标

    打开第二张图像,并将其转换成HSV色彩空间(代码中对输入的图像做了resize,避免有些图像尺寸过大,显示不全),然后对第一幅图像的直方图做反向投影。下面result是反向投影的结果,目前是框选了路飞的脸部作为感兴趣区域,如果框选路飞的帽子,反向投影会有不一样的效果,大家可以自己尝试。

    //打开第二幅图像,并转换成HSV,对第一幅图像的直方图做反向投影image = cv::imread("lufei2.JPG");resize(image, image3, cv::Size(500, 700));cv::cvtColor(image3, hsv, CV_BGR2HSV); //转换成HSV色彩空间int ch[1] = { 0 };cv::Mat result = finder.find(hsv, 0.0f, 180.0f, ch);

    openCV中如何实现meanshift算法查找目标

    使用openCV的meanshift算法可以将初始矩形区域修改成图像人物脸部的新位置。

    cv::TermCriteria criteria(cv::TermCriteria::MAX_ITER | cv::TermCriteria::EPS,10, // 最多迭代10 次1); // 或者重心移动距离小于1 个像素cv::meanShift(result, rect, criteria);

    openCV中如何实现meanshift算法查找目标

     至此,就找到了另一张图像中人物的脸部。

    三、其他实验结果

    除了进行从单人图像找另一个单人图像的实验,还做了从单人图像找多人合影的图像,下面是对NBA球星做的一个实验。

    openCV中如何实现meanshift算法查找目标

    openCV中如何实现meanshift算法查找目标

     四、部分原理补充

    本实验为了突出感兴趣目标特征,使用了HSV色彩空间的色调分量,使用CV_BGR2HSV标志转换图像后,得到的第一个通道就是色调分量。这是一个8位分量,值范围为0~180(如果使用cv::cvtColor,转换后的图像与原始图像的类型就会是相同的)。为了提取色调图像,cv::split 函数把三通道的 HSV 图像分割成三个单通道图像。这三幅图像存放在一个 std::vector 实例中,并且色调图像是向量的第一个入口(即索引为 0)。

    在使用颜色的色调分量时,要把它的饱和度考虑在内(饱和度是向量的第二个入口),当颜色的饱和度很低时,它的色调信息就会变得不稳定且不可靠。这是因为低饱和度颜色的 B、G 和 R 分量几乎是相等的,这导致很难确定它所表示的准确颜色。因此,在 getHueHistogram 方法中使用 minSat 参数屏蔽掉饱和度低于此阈值的像素,不把它们统计进直方图中。

    均值偏移算法是一个迭代过程,用于定位概率函数的局部最大值,方法是寻找预定义窗口内部数据点的重心或加权平均值。然后,把窗口移动到重心的位置,并重复该过程,直到窗口中心收敛到一个稳定的点。OpenCV 实现该算法时定义了两个停止条件:迭代次数达到最大值 (MAX_ITER);窗口中心的偏移值小于某个限值(EPS),可认为该位置收敛到一个稳定点。这两个条件存储在一个 cv::TermCriteria 实例中。

    五、完整代码

    #include <iostream>#include<Windows.h>#include<opencv2/core.hpp>    //图像数据结构的核心#include<opencv2/highgui.hpp> //所有图形接口函数#include<opencv2/imgproc.hpp>#include <opencv2/imgproc/types_c.h>#include<opencv2/imgproc/imgproc.hpp>#include<opencv2/opencv.hpp> using namespace std;using namespace cv; //获得色调直方图class ColorHistogram{private:int histSize[3]; // 每个维度的大小float hranges[2]; // 值的范围(三个维度用同一个值)const float* ranges[3]; // 每个维度的范围int channels[3]; // 需要处理的通道 public:ColorHistogram() {// 准备用于彩色图像的默认参数// 每个维度的大小和范围是相等的histSize[0] = histSize[1] = histSize[2] = 256;hranges[0] = 0.0; // BGR 范围为0~256hranges[1] = 256.0;ranges[0] = hranges; // 这个类中ranges[1] = hranges; // 所有通道的范围都相等ranges[2] = hranges;channels[0] = 0; // 三个通道:Bchannels[1] = 1; // Gchannels[2] = 2; // R} //计算一维直方图,BGR的原图转换成HSV,忽略低饱和度的像素cv::Mat getHueHistogram(const cv::Mat &image2, int minSaturation = 0){cv::Mat hist; //转换成HSV色彩空间cv::Mat hsv;cv::cvtColor(image2, hsv, CV_BGR2HSV);//cv::imshow("hsv", hsv); //掩码(可能用的到也可能用不到)cv::Mat mask;if (minSaturation > 0) {std::vector<cv::Mat>v;cv::split(hsv, v);  //将3个通道分割进3幅图像 cv::threshold(v[1], mask, minSaturation, 255, cv::THRESH_BINARY);//屏蔽低饱和度的像素} //准备一维色调直方图的参数hranges[0] = 0.0;hranges[1] = 180.0;  //范围是0~180channels[0] = 0;   //色调通道 //计算直方图cv::calcHist(&hsv, 1,   //仅为一幅图像的直方图channels,             //使用的通道mask,                 //二值掩码hist,                 //作为结果的直方图1,                    //这是一维的直方图histSize,             //箱子数量ranges);              //像素值的范围return hist;} }; class ContentFinder {private:// 直方图参数float hranges[2];const float* ranges[3];int channels[3];float threshold; // 判断阈值cv::Mat histogram; // 输入直方图public:ContentFinder() : threshold(0.1f) {// 本类中所有通道的范围相同ranges[0] = hranges;ranges[1] = hranges;ranges[2] = hranges;}// 对直方图做归一化void setHistogram(const cv::Mat& h) {histogram = h;cv::normalize(histogram, histogram, 1.0);} // 查找属于直方图的像素cv::Mat find(const cv::Mat& image, float minValue, float maxValue,int *channels) {cv::Mat result;hranges[0] = minValue;hranges[1] = maxValue;// 直方图的维度数与通道列表一致for (int i = 0; i < histogram.dims; i++)this->channels[i] = channels[i];cv::calcBackProject(&image, 1, // 只使用一幅图像channels, // 通道histogram, // 直方图result, // 反向投影的图像ranges, // 每个维度的值范围255.0 // 选用的换算系数// 把概率值从1 映射到255);cv::imshow("result", result);return result;}}; int main(){cv::Mat image = cv::imread("ZMS1.jpg");cv::Mat image2;cv::Mat image3;cv::Mat hsv;resize(image, image2, cv::Size(500, 700)); cv::Rect rect;rect = cv::selectROI("image", image2, false, false);cv::Mat imageROI = image2(rect).clone();//手动框选 //手动设置矩形框选范围 cv::rectangle(image2, rect, cv::Scalar(255, 0, 0), 1, cv::LINE_8, 0); cv::imshow("image2", image2);//得到人脸直方图int minsat = 65;  //最小饱和度ColorHistogram hc;cv::Mat colorhist = hc.getHueHistogram(imageROI, minsat);//把直方图传给ContentFinder类ContentFinder finder;finder.setHistogram(colorhist);//对直方图做归一化 //打开第二幅图像,并转换成HSV,对第一幅图像的直方图做反向投影image = cv::imread("ZMS2.JPG");resize(image, image3, cv::Size(500, 700));cv::cvtColor(image3, hsv, CV_BGR2HSV); //转换成HSV色彩空间int ch[1] = { 0 };cv::Mat result = finder.find(hsv, 0.0f, 180.0f, ch); cv::TermCriteria criteria(cv::TermCriteria::MAX_ITER | cv::TermCriteria::EPS,10, // 最多迭代10 次1); // 或者重心移动距离小于1 个像素cv::meanShift(result, rect, criteria);cv::rectangle(image3, rect, cv::Scalar(0, 255, 0), 1, cv::LINE_8, 0);cv::imshow("image3", image3);waitKey(0);}

    关于“openCV中如何实现meanshift算法查找目标”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    openCV中如何实现meanshift算法查找目标

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档

    猜你喜欢

    openCV中如何实现meanshift算法查找目标

    这篇文章将为大家详细讲解有关openCV中如何实现meanshift算法查找目标,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、简介图像直方图的反向投影是一个概率分布图,表示一个指定图像片段出现在特定位
    2023-06-25

    php如何实现查找算法

    小编给大家分享一下php如何实现查找算法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!php有什么特点1、执行速度快。2、具有很好的开放性和可扩展性。3、PHP支
    2023-06-14

    Python查找算法如何实现

    本文小编为大家详细介绍“Python查找算法如何实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“Python查找算法如何实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。查找算法是用来检索序列数据(群体)中是
    2023-06-30

    如何在Java项目中实现一个快速查找算法

    如何在Java项目中实现一个快速查找算法?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。快速查找算法,可以根据想要找的是第几个大的数,每次循环都能固定下来一个数在数组完整排完序之
    2023-05-31

    快速查找与二分查找算法如何在Java中实现

    这期内容当中小编将会给大家带来有关快速查找与二分查找算法如何在Java中实现,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1. 快速查找:这个是相当简单的,以数组举例,就用一个for循环去查找数组中需要查
    2023-05-31

    OpenCV如何实现图像去噪算法

    今天小编给大家分享一下OpenCV如何实现图像去噪算法的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一、函数参考1、Prim
    2023-07-02

    OpenCV如何实现无缝克隆算法

    这篇“OpenCV如何实现无缝克隆算法”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“OpenCV如何实现无缝克隆算法”文章吧
    2023-07-02

    怎么在java项目中实现一个二叉查找树算法

    今天就跟大家聊聊有关怎么在java项目中实现一个二叉查找树算法,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。具体内容如下package 查找;import edu.princeton
    2023-05-31

    Python+OpenCV如何实现基于颜色的目标识别

    这篇文章给大家介绍Python+OpenCV如何实现基于颜色的目标识别,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。任务让摄像头识别到视野范围内的气球并返回每个气球的中心点坐标。因为场地固定,背景单一,所以省下来很多操
    2023-06-22

    OpenCV-Python如何实现人脸磨皮算法

    这篇文章将为大家详细讲解有关OpenCV-Python如何实现人脸磨皮算法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。人脸磨皮是最基础的人脸美颜效果。主要分为祛斑,祛痘,淡化黑眼圈等步骤。通过前面的学习
    2023-06-15

    OpenCV-Python如何实现人脸美白算法

    这篇文章主要介绍了OpenCV-Python如何实现人脸美白算法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。人脸美白原理人脸美白原理说透了,就是一种图像的颜色空间处理,所以
    2023-06-15

    Python OpenCV Canny边缘检测算法如何实现

    本文小编为大家详细介绍“Python OpenCV Canny边缘检测算法如何实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“Python OpenCV Canny边缘检测算法如何实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入
    2023-07-02

    FloydWarshall算法如何在java项目中实现

    这期内容当中小编将会给大家带来有关FloydWarshall算法如何在java项目中实现,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。求一个图中任意两点之间的最短路径 FloydWarshall
    2023-05-31

    C++ opencv如何利用grabCut算法实现抠图

    今天小编给大家分享一下C++ opencv如何利用grabCut算法实现抠图的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。前
    2023-06-30

    Python OpenCV Hough直线检测算法如何实现

    这篇文章主要介绍了Python OpenCV Hough直线检测算法如何实现的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Python OpenCV Hough直线检测算法如何实现文章都会有所收获,下面我们一起
    2023-07-02

    C++如何实现并查集算法

    这篇文章主要介绍了C++如何实现并查集算法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1、并查集的初始化并查集是用一个数组实现的。首先先定义一个数组:int father[
    2023-06-29

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录