Opencv Camshift对象跟踪详细代码
第一步:相机标定,获取相机内参和外参
第二步:建立像素坐标系与世界坐标系的转换关系
第三步:通过手动ROI选择视频中感兴趣区域
第四步:获取ROI区域的中心作为跟踪目标的目标像素点
第五步:实时计算像素点对应的空间姿态,同时显示目标跟踪情况

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <math.h>
#include <stdio.h>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/videoio.hpp>
#include <chrono>
#include <fstream>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>#include "opencv2/calib3d/calib3d.hpp"
#include <cctype>
#include <string.h>
#include <time.h>#include <windows.h>
#include <cstdio>
#include<windows.h>
#include"glew.h"
#include<GL/GL.h>
#include<GL/GLU.h>//#include <sl/Camera.hpp>using namespace std;
using namespace cv;int smin = 15;
int vmin = 40;
int vmax = 256;
int bins = 16;Point3f getWorldPoints(Point2f &inPoints, cv::Mat &rvec, cv::Mat &tvec, cv::Mat &cameraMatrix)
{double zConst = 0;//实际坐标系的距离,若工作平面与相机距离固定可设置为0double s;//获取图像坐标(2*1转为3*1)cv::Mat imagePoint = (Mat_<double>(3, 1) << double(inPoints.x), double(inPoints.y), 1);//计算比例参数Scv::Mat tempMat, tempMat2;tempMat = rvec.inv() * cameraMatrix.inv() * imagePoint;tempMat2 = rvec.inv() * tvec;s = zConst + tempMat2.at<double>(2, 0);s /= tempMat.at<double>(2, 0);//计算世界坐标cv::Mat wcPoint = rvec.inv() * (s * cameraMatrix.inv() * imagePoint - tvec);Point3f worldPoint(wcPoint.at<double>(0, 0), wcPoint.at<double>(1, 0), wcPoint.at<double>(2, 0));cout << "世界坐标系 x = " << worldPoint.x << " y = " << worldPoint.y << " z = " << worldPoint.z << endl;return worldPoint;
}int main(int argc, char** argv) {VideoCapture capture;//capture.open("E:/图片/data/4.mp4");capture.open(0);capture.set(CAP_PROP_FRAME_WIDTH, 1920.0);capture.set(CAP_PROP_FRAME_HEIGHT, 1440.0);if (!capture.isOpened()) {printf("could not find video data file...\n");return -1;}namedWindow("CAMShift Tracking", CV_WINDOW_AUTOSIZE);namedWindow("ROI Histogram", CV_WINDOW_AUTOSIZE);//设置全屏//setWindowProperty("CAMShift Tracking", CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);bool firstRead = true;//确认是否为第一帧float hrange[] = { 0, 180 };const float* hranges = hrange;Rect selection;Mat frame,hsv, hue, mask, hist, backprojection;Mat grayImage;//直方图Mat drawImg = Mat::zeros(300, 300, CV_8UC3);Mat cameraMatrix = (Mat_<double>(3, 3) <<1056.6000, 0, 978.9200,0, 1055.6600, 534.1640,0, 0, 1);Mat rvec = (Mat_<double>(3, 3) <<0.9967, -0.0158, 0.0793,0.01889, 0.9991, -0.0381,-0.0787, 0.0396, 0.9961);Mat tvec = (Mat_<double>(3, 1) <<-128.5678,-12.7116,-0.6481);while (capture.read(frame)) {if (firstRead) {//first为第一帧选择的ROI区域   frame为第一帧Rect2d first = selectROI("CAMShift Tracking", frame);//选择ROI区域//Rect2d first = selectROI("CAMShift Tracking", hsv);//选择ROI区域//初始化  将鼠标选择的ROI区域参数赋予程序定义的Rect selectionselection.x = first.x;selection.y = first.y;selection.width = first.width;selection.height = first.height;printf("ROI.x= %d, ROI.y= %d, width = %d, height= %d", selection.x, selection.y, selection.width, selection.height);}// convert to HSVcvtColor(frame, hsv, COLOR_BGR2HSV);//inRange检查数组元素是否在另外两个数组元素值之间//参数:(输入要处理的图像(可以是单通道也可以是多通道),包含下边界数组标量(即H,S,V最小值)//包含下边界数组标量(即H,S,V最大值),输出图像)inRange(hsv, Scalar(0, smin, vmin), Scalar(180, vmax, vmax), mask);//提取H通道hue = Mat(hsv.size(), hsv.depth());//HSV对应通道0,1,2,H通道对应0//因此将输入图像HSV的0通道  复制到   H的0通道int channels[] = { 0, 0 };//mixChannels()函数用于将输入数组的指定通道复制到输出数组的指定通道//参数(输入数组或向量矩阵,矩阵数量,输出数组或矩形向量,矩阵数量//指定被复制通道与要复制到的位置组成的索引对,索引对数目)//例如:将一个4通道BGRA图像分割成3通道BGR和一通道A图像mixChannels(&hsv, 1, &hue, 1, channels, 1);if (firstRead) {// ROI 直方图计算//通过selection(鼠标)选择的hue和mask的区域分别命名为roi和maskroiMat roi(hue, selection);Mat maskroi(mask, selection);//calcHist计算直方图//参数:(输入图像,输入图像的个数,需要统计直方图的第几个通道//掩膜(计算掩膜内的直方图),输出直方图数组,需要统计直方图通道的个数//直方图分成多少个区间,统计像素值的区间)//掩膜:用选定的图像对处理的图像进行遮挡,来控制图像处理的区域calcHist(&roi, 1, 0, maskroi, hist, 1, &bins, &hranges);//归一化normalize(hist, hist, 0, 255, NORM_MINMAX);// show histogram直方图//一个有16个bin,每个bin的宽度binwint binw = drawImg.cols / bins;//颜色索引 一个图片分成16个bin,每个bin对应一种颜色Mat colorIndex = Mat(1, bins, CV_8UC3);for (int i = 0; i < bins; i++) {colorIndex.at<Vec3b>(0, i) = Vec3b(saturate_cast<uchar>(i * 180 / bins), 255, 255);}//原来色彩取值是0-180,现在转换RGB的0-255cvtColor(colorIndex, colorIndex, COLOR_HSV2BGR);//绘制直方图for (int i = 0; i < bins; i++) {int  val = saturate_cast<int>(hist.at<float>(i)*drawImg.rows / 255);//把直方图用矩形表示//参数(输入图像,矩形的一个顶点,矩形对角线上的另一个顶点,线条颜色,粗细....)rectangle(drawImg, Point(i*binw, drawImg.rows), Point((i + 1)*binw, drawImg.rows - val), Scalar(colorIndex.at<Vec3b>(0, i)), -1, 8, 0);}}// back projection----计算直方图反向映射//反投射直方图原理:直方图可以作为图像的一个描述特征,计算出A的直方图//且假设计算出来的值可以有效地代表A,之后遍历图像B,使用B的每一个像素点对应A//的直方图中的统计值来替代原来的像素值//参数(输入图像(必须是CV_8U,CV_16U,CV_32U的一种),输入图像的数量//计算方向投影的通道(这里是第0通道),输入的直方图,目标反向投影输出图像//直方图每个维度bin的取值范围)calcBackProject(&hue, 1, 0, hist, backprojection, &hranges);// CAMShift trackingbackprojection &= mask;//CamShift参数:(色彩概率分布图像,选择的窗口初始值,用来判断搜寻是否停止的一个标准//保存运行结果,包含被跟踪物体的最小矩形)//TermCriteria::COUNT 和 TermCriteria::EPS 为终止条件类型RotatedRect trackBox = CamShift(backprojection, selection, TermCriteria((TermCriteria::COUNT | TermCriteria::EPS), 10, 1));// draw location on frame;//参数(图像,绘制椭圆圆弧所需要的外接矩形,颜色,粗细,线条类型//ellipse(frame, trackBox, Scalar(0, 0, 255), 3, 8);ellipse(hsv, trackBox, Scalar(0, 0, 255), 3, 8);//定义椭圆的中点Point2f center; //定义变量center = trackBox.center;//读取椭圆中心//circle(frame, center, 1, Scalar(0, 255, 0), 2, 8, 0);circle(hsv, center, 1, Scalar(0, 255, 0), 2, 8, 0);cout <<"像素坐标系 x = "<< center.x << " y = " << center.y << endl;//将像素坐标转为世界坐标getWorldPoints(center, rvec, tvec, cameraMatrix);if (firstRead) {firstRead = false;}//imshow("CAMShift Tracking", frame);imshow("CAMShift Tracking", hsv);imshow("ROI Histogram", drawImg);char c = waitKey(50);// ESCif (c == 27) {break;}waitKey(10);}capture.release();waitKey(0);return 0;
}

Opencv Camshift对象跟踪相关推荐

  1. opencv实现对象跟踪_如何使用opencv跟踪对象的距离和角度

    opencv实现对象跟踪 介绍 (Introduction) Tracking the distance and angle of an object has many practical uses, ...

  2. OpenCV 实时对象跟踪(质心跟踪)

    本文章先介绍对象跟踪过程,考虑对象跟踪的特点决定使用:质心跟踪算法,然后会一步一步说明质心跟踪算法的实现:最后是如何用python代码实现. 实验效果如下: 对象跟踪过程 进行一组初始的对象检测(如: ...

  3. 使用 OpenCV 进行对象跟踪的几种算法解读

    使用 OpenCV 进行对象跟踪--算法 在本节中,我们将深入研究不同的跟踪算法.目标不是对每个跟踪器有深入的理论理解,而是从实践的角度理解它们. 让我首先解释跟踪背后的一些一般原则.在跟踪中,我们的 ...

  4. opencv视频分析与对象追踪之CAMSHIFT对象跟踪

    原理 CamShift算法,全称是 Continuously AdaptiveMeanShift,顾名思义,它是对Mean Shift 算法的改进,能够自动调节搜索窗口大小来适应目标的大小,可以跟踪视 ...

  5. Opencv实现对象跟踪

    文章目录 1.轮廓查找和轮廓绘制 2.高斯去噪 3.腐蚀和膨胀 4.cv2.inRange函数 5.cv2.minEnclosingCircle函数 6.cv2.moments函数 7.代码实战 1. ...

  6. OpenCV连续自适应跟踪算法CAMShift实现视频对象跟踪

    1.概述 案例:使用OpenCV的CAMShift算法实现视频中对象跟踪 算法API介绍: 本文福利,莬费领取Qt开发学习资料包.技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,Q ...

  7. 目标跟踪(7)使用 OpenCV 进行简单的对象跟踪

    1.简述 目标跟踪的过程是: 1.获取对象检测的初始集(例如边界框坐标的输入集) 2.为每个初始检测创建唯一的ID 3.然后跟踪每一个在视频中移动的对象,保持唯一ID的分配 此外,对象跟踪允许我们为每 ...

  8. OpenCV视频分析与对象跟踪实战教程-贾志刚-专题视频课程

    OpenCV视频分析与对象跟踪实战教程-1957人已学习 课程介绍         OpenCV视频分析与对象跟踪实战视频培训课程概况:基于OpenCV新版本3.2 从基本的OpenCV视频读写与摄像 ...

  9. 【opencv】Camshift目标跟踪

    Camshift原理 CamShift算法的全称是"Continuously Adaptive Mean-SHIFT",即:连续自适应的MeanShift算法.其基本思想是对视频序 ...

  10. Java OpenCV 图像处理30 视频分析和对象跟踪 视频读取

    Java OpenCV 图像处理30 视频分析和对象跟踪 视频读取 Java OpenCV-4.0.0 图像处理 视频分析和对象跟踪 视频读取 package com.xu.opencv.video; ...

最新文章

  1. 终于找到可以一文多发的平台了!
  2. 10分钟教你看懂mongodb的npm包
  3. 魅族 C++ 微服务框架技术内幕揭秘
  4. QPW 公告表(tf_notice)
  5. tf.name_scope()详解【命名空间其实就是给几个变量包一层名字,方便变量管理】
  6. 火狐浏览器设置_[教程] 在谷歌浏览器和火狐浏览器里配置DoH加密DNS流量提高安全性...
  7. c 语言 移位四舍五入,关于C 语言中的四舍五入问题
  8. python与线性代数 线性方程组的解集
  9. Linux内核为什么会发生soft lockup?
  10. 慎用JSON.stringify
  11. php探针教程,php探针程序的推荐
  12. html如何在表单里加虚线,大佬,表格下方的虚线怎么添加?
  13. 嵌入式常用裸机编程框架
  14. Java 习题 (12)
  15. 汇正财经骗局?科创50大涨
  16. 搭建JIRA避坑指南
  17. 920记者招待会: 对话详解海尔张瑞敏首席的人单合一
  18. 涩会:广告商怎么获取到用户隐私资料的
  19. 华硕fl8000u是什么型号_华硕fl8000u怎么样 华硕笔记本fl8000u配置是什么
  20. Win32绘制PNG

热门文章

  1. kettle(PDI)安装使用过程,并部署到Linux下执行定时作业
  2. loadrunner 11 破解
  3. 常用电子元器件检测方法与经验
  4. Hyperion神器之SmartView产品(下篇)
  5. 谷歌浏览器截图_【插件推荐】一键滚动截图整个网页,支持二次编辑的免费工具...
  6. 微信小程序蓝牙连接TSPL打印机打印图片思路
  7. jmeter的json提取器提取数据
  8. ORACLE P6 21.12 系统虚拟机(VM)分享
  9. 高通QCA9377 WiFi蓝牙模块芯片介绍
  10. Tomcat 7 部署和配置