针对动态背景下的目标检测定位

#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/features2d/features2d.hpp>
#include<opencv2/nonfree/nonfree.hpp>
#include<opencv2/calib3d/calib3d.hpp>
#include<opencv2/stitching/stitcher.hpp>
#include<iostream>
#include<vector>
#include<Windows.h>
#include<sstream>
#include<time.h>
#include<fstream>
#include<math.h>using namespace cv;
using namespace std;//定义全局变量
Rect pre_Rect;//定义初始帧的框
int shrink = 4;//图片帧缩小倍数
int frame_num = 1;//记录循环帧数
ofstream recordFile("E:\\软件所资料\\科创项目材料\\图片\\all_pic3(1.2)\\纪录处理时间.txt");//创建记录文件//运动物体检测函数声明
Mat MoveDetect(Mat temp, Mat frame);
//基于特征点匹配的图像拼接
void stitch(Mat& srcImage1, Mat& srcImage2, Mat& panorama);
//读入视频帧   调用stitch2函数进行拼接
void readVideo(string videoName);
//求矩形的中心点
Point getCenterPoint(Rect rect);
//获取两点间的距离
double getDistance(Point p1, Point p2);
//手动标框
void onMouse(int event, int x, int y, int, void *);int main(int argc, char* argv[]) {//pre_Rect = Rect(Point(1050, 520), Point(1160, 580));//自己设定的初始矩形框pre_Rect = Rect(Point(260, 130), Point(300, 150));//自己设定的初始矩形框readVideo("E:\\软件所资料\\录制视频\\test.mov");return 0;
}//读入视频帧   调用stitch函数进行拼接
void readVideo(string videoName) {VideoCapture videoCap(videoName);if (!videoCap.isOpened()) {exit;}Mat preFrame;//先前帧Mat nowFrame;//当前帧Mat stichFrame;//拼接帧Mat resultFrame;//结果帧//函数回调   鼠标事件namedWindow("result", 1);setMouseCallback("result", onMouse, 0);clock_t start, finish, all_start, all_finish;//计算程序运行时间double processTime, totalTime = 0;videoCap >> preFrame;GaussianBlur(preFrame, preFrame, Size(5, 5), 0, 0);//高斯滤波器去除图像中噪点resize(preFrame, preFrame, Size(preFrame.cols / shrink, preFrame.rows / shrink));//imshow("first", preFrame);//int count = 1;while (true) {all_start = clock();//纪录总的开始时间videoCap >> nowFrame;GaussianBlur(nowFrame, nowFrame, Size(5, 5), 0, 0);//高斯滤波器去除图像中噪点if (nowFrame.empty()) {recordFile << "平均处理时间:" << totalTime / frame_num << "ms" << "\n" << "\n";recordFile.close();break;}resize(nowFrame, nowFrame, Size(nowFrame.cols / shrink, nowFrame.rows / shrink));recordFile << frame_num++ << "\n";Mat temp;start = clock();stitch(nowFrame, preFrame, temp);finish = clock();recordFile << "拼接用时:" << finish - start << "ms" << "\n";if (temp.empty()) {stichFrame = nowFrame;}else {stichFrame = temp;}start = clock();resultFrame = MoveDetect(nowFrame, stichFrame);finish = clock();recordFile << "减差和检测用时:" << finish - start << "ms" << "\n";all_finish = clock();//纪录总的结束时间processTime = all_finish - all_start;recordFile << "共运行:" << processTime << "ms" << "\n" << "\n";totalTime += processTime;//拼接字符串String imageName = "E:\\软件所资料\\科创项目材料\\图片\\all_pic3(1.2)\\第";//字符串检测图片名称//数字转换成字符串
        ostringstream strCount;strCount << frame_num;string str = strCount.str();imageName.append(str);imageName.append("帧图片.jpg");imwrite(imageName, resultFrame);imshow("result", resultFrame);waitKey(1);preFrame = nowFrame.clone();//当前帧nowFrame赋给上一帧preFrame;
}
}//基于特征点匹配的图像拼接
void stitch(Mat& srcImage1, Mat& srcImage2, Mat& panorama) {clock_t start;clock_t finish;start = clock();Mat srcImage2Warped;//SURF特征点描述int minHessian = 400; //Hessian海塞矩阵阈值 原值400,在这里调整精度,值越大点越小,越精准
    SurfFeatureDetector detector(minHessian);vector<KeyPoint> kPointMat, kPointMat2;detector.detect(srcImage1, kPointMat);detector.detect(srcImage2, kPointMat2);//计算特征向量
    SurfDescriptorExtractor extractor;Mat desMat1, desMat2;//存放特征向量的矩阵
    extractor.compute(srcImage1, kPointMat, desMat1);extractor.compute(srcImage2, kPointMat2, desMat2);////ORB特征点检测//ORB orb;//vector<KeyPoint> kPointMat, kPointMat2;//orb.detect(srcImage1,kPointMat);//orb.detect(srcImage2, kPointMat2);
finish = clock();cout << "特征点检测时间" << finish - start << endl;start = clock();//FLANN关键点匹配//FLANN初始化、RANSAC一致性、最近邻特征
    BFMatcher matcher;vector<DMatch> matches;matcher.match(desMat1, desMat2, matches);double min_dist = 100 * 1.0 / shrink;//double max_dist = 0;//特征点最大与最小距离查找for (int i = 0; i < desMat1.rows; i++) {double dist = matches[i].distance;if (dist < min_dist) min_dist = dist;//if (dist > max_dist) max_dist = dist;
    }//使用good特征构建距离限定vector<DMatch> good_matches;for (int i = 0; i < desMat1.rows; i++) {//特征点最优距离筛选if (matches[i].distance < 3 * min_dist) {  //距离筛选  原值3*min_dist
            good_matches.push_back(matches[i]);}}//图像的关键点匹配vector<Point2f> srcImage1_matchedKPs;vector<Point2f> srcImage2_matchedKPs;for (size_t i = 0; i < good_matches.size(); i++) {srcImage1_matchedKPs.push_back(kPointMat[good_matches[i].queryIdx].pt);srcImage2_matchedKPs.push_back(kPointMat2[good_matches[i].trainIdx].pt);}finish = clock();cout << "关键点匹配时间" << finish - start << endl;//关键点匹配try {start = clock();//计算图像1与图像2的映射Mat H = findHomography(Mat(srcImage2_matchedKPs), Mat(srcImage1_matchedKPs), CV_RANSAC);//仿射变换
        warpPerspective(srcImage2, srcImage2Warped, H, Size(srcImage2.cols, srcImage2.rows), INTER_CUBIC);//imshow("srcImage2Warped", srcImage2Warped);panorama = srcImage2Warped.clone();//写入结合帧图片//拼接字符串String imageName = "E:\\软件所资料\\科创项目材料\\图片\\all_pic3(1.2)\\结合帧\\第";//字符串检测图片名称//数字转换成字符串
        ostringstream strCount;strCount << frame_num;string str = strCount.str();imageName.append(str);imageName.append("帧图片.jpg");imwrite(imageName, panorama);finish = clock();cout << "仿射变换时间" << finish - start << endl;//关键点匹配cout << endl;}catch (Exception e) {exit;}}//Point pt1 = Point(260, 130), pt2 = Point(290, 150);
//帧差和目标检测
Mat MoveDetect(Mat temp, Mat frame)
{Mat result = temp.clone();//1.将background和frame转为灰度图
    Mat gray1, gray2;cvtColor(temp, gray1, CV_BGR2GRAY);cvtColor(frame, gray2, CV_BGR2GRAY);//2.将background和frame做差  Mat diff = Mat::zeros(temp.rows, temp.cols, CV_8UC1);cvtColor(temp, temp, CV_RGB2GRAY);cvtColor(frame, frame, CV_RGB2GRAY);//写入结合帧灰度图//拼接字符串String imageName = "E:\\软件所资料\\科创项目材料\\图片\\all_pic3(1.2)\\结合帧灰度图\\第";//字符串检测图片名称//数字转换成字符串
    ostringstream strCount;strCount << frame_num;string str = strCount.str();imageName.append(str);imageName.append("帧图片.jpg");imwrite(imageName, frame);//写入普通帧灰度图//拼接字符串String imageName1 = "E:\\软件所资料\\科创项目材料\\图片\\all_pic3(1.2)\\普通帧灰度图\\第";//字符串检测图片名称//数字转换成字符串
    ostringstream strCount1;strCount1 << frame_num;string str1 = strCount1.str();imageName1.append(str1);imageName1.append("帧图片.jpg");imwrite(imageName1, temp);//膨胀  去原图像毛边Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));//原数值为3,3
    dilate(temp, temp, element);dilate(frame, frame, element);//帧差法 直接灰度值相减for (int i = 0; i < diff.cols - 1; i++){for (int j = 0; j < diff.rows - 1; j++){int t1 = 20, t2 = 200;if (temp.at<uchar>(j, i) - frame.at<uchar>(j, i) >= t1 && temp.at<uchar>(j, i) - frame.at<uchar>(j, i) <= t2){diff.at<uchar>(j, i) = 255;//temp.at<uchar>(j, i) - frame.at<uchar>(j, i);
            }else if (frame.at<uchar>(j, i) - temp.at<uchar>(j, i) >= t1 && frame.at<uchar>(j, i) - temp.at<uchar>(j, i) <= t2){diff.at<uchar>(j, i) = 255;//frame.at<uchar>(j, i) - temp.at<uchar>(j, i);
            }}}//写入帧差后灰度图//拼接字符串String imageName2 = "E:\\软件所资料\\科创项目材料\\图片\\all_pic3(1.2)\\帧差后灰度图\\第";//字符串检测图片名称//数字转换成字符串
    ostringstream strCount2;strCount2 << frame_num;string str2 = strCount2.str();imageName2.append(str2);imageName2.append("帧图片.jpg");imwrite(imageName2, diff);////获取自定义核//Mat element1 = getStructuringElement(MORPH_RECT, Size(2, 2)); //MORPH_RECT 原数值Size(2,2) 第一个参数MORPH_RECT表示矩形的卷积核,当然还可以选择椭圆形的、交叉型的 ////腐蚀操作//morphologyEx(diff, diff, MORPH_OPEN, element1);//开运算  先腐蚀后膨胀  去除小的物体
Mat element1 = getStructuringElement(MORPH_RECT, Size(3, 3)); //MORPH_RECT 原数值Size(2,2) 第一个参数MORPH_RECT表示矩形的卷积核,当然还可以选择椭圆形的、交叉型的 dilate(diff, diff, element1, Point(-1, -1), 3);//写入帧差和形态学处理后灰度图//拼接字符串String imageName3 = "E:\\软件所资料\\科创项目材料\\图片\\all_pic3(1.2)\\帧差和形态学处理后灰度图\\第";//字符串检测图片名称//数字转换成字符串
    ostringstream strCount3;strCount3 << frame_num;string str3 = strCount3.str();imageName3.append(str3);imageName3.append("帧图片.jpg");imwrite(imageName3, diff);/*for (int j = pt1.y + 5; j > pt1.y - 5; j--){int flag = 0;for (int i = pt1.x; i < pt2.x; i++){if (diff.at<uchar>(j, i) > 0){flag = 1;break;}}if (flag == 0){pt1.y = j;break;}}for (int j = pt2.y - 5; j < pt2.y + 5; j++){int flag = 0;for (int i = pt1.x; i < pt2.x; i++){if (diff.at<uchar>(j, i) > 0){flag = 1;break;}}if (flag == 0){pt2.y = j;break;}}for (int i = pt1.x + 5; i > pt1.x - 5; i--){int flag = 0;for (int j = pt1.y; j < pt2.y; j++){if (diff.at<uchar>(j, i) > 0){flag = 1;break;}}if (flag == 0){pt1.x = i;break;}}for (int i = pt2.x - 5; i < pt2.x + 5; i++){int flag = 0;for (int j = pt1.y; j < pt2.y; j++){if (diff.at<uchar>(j, i) > 0){flag = 1;break;}}if (flag == 0){pt2.x = i;break;}}cout << pt1 << pt2 << endl;Mat diff1 = diff.clone();cvtColor(diff1, diff1, CV_GRAY2RGB);line(diff1, Point(pt1.x, pt1.y), Point(pt2.x, pt1.y), Scalar(0, 0, 255), 1, 8);line(diff1, Point(pt1.x, pt2.y), Point(pt2.x, pt2.y), Scalar(0, 0, 255), 1, 8);line(diff1, Point(pt1.x, pt1.y), Point(pt1.x, pt2.y), Scalar(0, 0, 255), 1, 8);line(diff1, Point(pt2.x, pt1.y), Point(pt2.x, pt2.y), Scalar(0, 0, 255), 1, 8);imwrite(imageName3, diff1);*///6.查找轮廓并绘制轮廓  vector<vector<Point> > contours;findContours(diff, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);//drawContours(result, contours, -1, Scalar(0, 0, 255), 2);//在result上绘制轮廓  //7.查找正外接矩形  vector<Rect> boundRect(contours.size());int pre_Rect_width = (pre_Rect.br().x - pre_Rect.tl().x);//上一个目标框的宽int pre_Rect_height = (pre_Rect.br().y - pre_Rect.tl().y);//上一个目标框的高int pre_Rect_x = pre_Rect.tl().x + pre_Rect_width / 2, pre_Rect_y = pre_Rect.tl().y + pre_Rect_height / 2;//上一个位置的中心点//在上一个矩形标注框的3*3的区域搜索矩形int search_lt_x = pre_Rect.tl().x - 1.0 * pre_Rect_width;//左上角点的x值int search_lt_y = pre_Rect.tl().y - 1.0 * pre_Rect_height;//左上角点的y值int search_br_x = pre_Rect.br().x + 1.0 * pre_Rect_width;//右下角点的x值int search_br_y = pre_Rect.br().y + 1.0 * pre_Rect_height;//右下角的y值Point search_lt = Point(search_lt_x, search_lt_y);//左上角点Point search_br = Point(search_br_x, search_br_y);//右下角点Rect search_Rect = Rect(search_lt, search_br);//搜索矩形vector<Rect> search_area_boundRect(contours.size());int search_rect_count = 0;//搜索区域内的矩形数量//遍历所有的轮廓矩形 挑选出搜索区域内的轮廓矩形加入到search_area_boundRect可变数组中for (int i = 0; i < contours.size(); i++){boundRect[i] = boundingRect(contours[i]);//边缘矩形赋值给定义的矩形数组元素if (boundRect[i].tl().y < (50 * 1.0 / shrink) || boundRect[i].tl().x < (50 * 1.0 / shrink) || boundRect[i].br().x>(1700 * 1.0 / shrink) || boundRect[i].br().y>(900 * 1.0 / shrink)) {//去除边缘矩形continue;}//判断矩形相交或搜索矩形包含轮廓矩形 条件1-4满足任意一个即可判断其相交或包含bool limit1 = (boundRect[i].tl().x > search_lt_x&&boundRect[i].tl().x < search_br_x) && (boundRect[i].tl().y > search_lt_y&&boundRect[i].tl().y < search_br_y); //该矩形左上角在搜索区域内//用轮廓矩形左上角的y右下角的x值代替右上角的值int boundRect_rt_x = boundRect[i].br().x;int boundRect_rt_y = boundRect[i].tl().y;bool limit2 = (boundRect_rt_x > search_lt_x&&boundRect_rt_x < search_br_x) && (boundRect_rt_y > search_lt_y&&boundRect_rt_y < search_br_y);//该矩形右上角在搜索区域内bool limit3 = (boundRect[i].br().x > search_lt_x&&boundRect[i].br().x < search_br_x) && (boundRect[i].br().y > search_lt_y&&boundRect[i].br().y < search_br_y); //该矩形右下角在搜索区域内//用轮廓的矩形左上角的x右下角的y值代替左下角的值int boundRect_bl_x = boundRect[i].tl().x;int boundRect_bl_y = boundRect[i].br().y;bool limit4 = (boundRect_bl_x > search_lt_x&&boundRect_bl_x < search_br_x) && (boundRect_bl_y > search_lt_y&&boundRect_bl_y < search_br_y);//该矩形右上角在搜索区域内if (limit1 || limit2 || limit3 || limit4) {if (boundRect[i].width < 3 * boundRect[i].height&&boundRect[i].height < 3 * boundRect[i].width) {//去除长条的矩形//求该矩形中心到上一个定位框中心点距离 挑出小于上一个对角线一半的矩形框Point boundRectCenterPoint = getCenterPoint(boundRect[i]);Point preRectCenterPoint = getCenterPoint(pre_Rect);double dis = getDistance(boundRectCenterPoint, preRectCenterPoint);//求上一个矩形定位框对角线一半的距离double diagonal = sqrt(pow(pre_Rect.width, 2) + pow(pre_Rect.height, 2));//对角线的距离if (dis <= diagonal / 2) {search_area_boundRect[search_rect_count++] = boundRect[i];//找出矩形搜索区域内的所有轮廓矩形放入可变数组中
                }rectangle(result, boundRect[i], Scalar(0, 255, 0), 2);//在result上绘制选出的搜索区域内的正外接矩形
            }}//rectangle(result, boundRect[i], Scalar(0, 255, 0), 2);//在result上绘制正外接矩形rectangle(result, search_Rect, Scalar(255, 0, 0), 2);}//如果在距离上一个定位框中心点的距离小于对角线一半的矩形一个都没有   则扩大区域在搜索框中寻找轮廓框(距离上一定位框小于对角线一半的优先级高于搜索框)if (search_rect_count == 0) {for (int i = 0; i < contours.size(); i++){boundRect[i] = boundingRect(contours[i]);//边缘矩形赋值给定义的矩形数组元素if (boundRect[i].tl().y < (50 * 1.0 / shrink) || boundRect[i].tl().x < (50 * 1.0 / shrink) || boundRect[i].br().x>(1700 * 1.0 / shrink) || boundRect[i].br().y>(900 * 1.0 / shrink)) {//边缘矩形//boundRect[i] = Rect(pre_Rect_x, pre_Rect_y, 1, 1);//边缘矩形 加进去上一个位置点continue;}//在上一个矩形标注框的3*3的区域搜索矩形int search_lt_x = pre_Rect.tl().x - 1.0 * pre_Rect_width;//左上角点的x值int search_lt_y = pre_Rect.tl().y - 1.0 * pre_Rect_height;//左上角点的y值int search_br_x = pre_Rect.br().x + 1.0 * pre_Rect_width;//右下角点的x值int search_br_y = pre_Rect.br().y + 1.0 * pre_Rect_height;//右下角的y值Point search_lt = Point(search_lt_x, search_lt_y);//左上角点Point search_br = Point(search_br_x, search_br_y);//右下角点Rect search_Rect = Rect(search_lt, search_br);//搜索矩形//判断矩形相交或搜索矩形包含轮廓矩形 条件1-4满足任意一个即可判断其相交或包含bool limit1 = (boundRect[i].tl().x > search_lt_x&&boundRect[i].tl().x < search_br_x) && (boundRect[i].tl().y > search_lt_y&&boundRect[i].tl().y < search_br_y); //该矩形左上角在搜索区域内//用轮廓矩形左上角的y右下角的x值代替右上角的值int boundRect_rt_x = boundRect[i].br().x;int boundRect_rt_y = boundRect[i].tl().y;bool limit2 = (boundRect_rt_x > search_lt_x&&boundRect_rt_x < search_br_x) && (boundRect_rt_y > search_lt_y&&boundRect_rt_y < search_br_y);//该矩形右上角在搜索区域内bool limit3 = (boundRect[i].br().x > search_lt_x&&boundRect[i].br().x < search_br_x) && (boundRect[i].br().y > search_lt_y&&boundRect[i].br().y < search_br_y); //该矩形右下角在搜索区域内//用轮廓的矩形左上角的x右下角的y值代替左下角的值int boundRect_bl_x = boundRect[i].tl().x;int boundRect_bl_y = boundRect[i].br().y;bool limit4 = (boundRect_bl_x > search_lt_x&&boundRect_bl_x < search_br_x) && (boundRect_bl_y > search_lt_y&&boundRect_bl_y < search_br_y);//该矩形右上角在搜索区域内if ((limit1 || limit2 || limit3 || limit4)) {if (boundRect[i].width < 3 * boundRect[i].height&&boundRect[i].height < 3 * boundRect[i].width) {//去除长条的矩形search_area_boundRect[search_rect_count++] = boundRect[i];rectangle(result, boundRect[i], Scalar(0, 255, 0), 2);}}rectangle(result, search_Rect, Scalar(255, 0, 0), 2);//在result上绘制正外接搜索矩形框 //rectangle(result, boundRect[i], Scalar(0, 255, 0), 2);//在result上绘制正外接矩形
}}////如果还没找到扩大搜索框为5*5//if (search_rect_count == 0) {//    for (int i = 0; i < contours.size(); i++)//    {//        boundRect[i] = boundingRect(contours[i]);//边缘矩形赋值给定义的矩形数组元素//        if (boundRect[i].tl().y < (50 * 1.0 / shrink) || boundRect[i].tl().x < (50 * 1.0 / shrink) || boundRect[i].br().x>(1700 * 1.0 / shrink) || boundRect[i].br().y>(900 * 1.0 / shrink)) {//边缘矩形//            //boundRect[i] = Rect(pre_Rect_x, pre_Rect_y, 1, 1);//边缘矩形 加进去上一个位置点//            continue;//        }//        //在上一个矩形标注框的3*3的区域搜索矩形//        int search_lt_x = pre_Rect.tl().x - 1.2 * pre_Rect_width;//左上角点的x值//        int search_lt_y = pre_Rect.tl().y - 1.2 * pre_Rect_height;//左上角点的y值//        int search_br_x = pre_Rect.br().x + 1.2 * pre_Rect_width;//右下角点的x值//        int search_br_y = pre_Rect.br().y + 1.2 * pre_Rect_height;//右下角的y值//        Point search_lt = Point(search_lt_x, search_lt_y);//左上角点//        Point search_br = Point(search_br_x, search_br_y);//右下角点//        Rect search_Rect = Rect(search_lt, search_br);//搜索矩形//        //判断矩形相交或搜索矩形包含轮廓矩形 条件1-4满足任意一个即可判断其相交或包含//        bool limit1 = (boundRect[i].tl().x > search_lt_x&&boundRect[i].tl().x < search_br_x) && (boundRect[i].tl().y > search_lt_y&&boundRect[i].tl().y < search_br_y); //该矩形左上角在搜索区域内//        //用轮廓矩形左上角的y右下角的x值代替右上角的值//        int boundRect_rt_x = boundRect[i].br().x;//        int boundRect_rt_y = boundRect[i].tl().y;//        bool limit2 = (boundRect_rt_x > search_lt_x&&boundRect_rt_x < search_br_x) && (boundRect_rt_y > search_lt_y&&boundRect_rt_y < search_br_y);//该矩形右上角在搜索区域内//        bool limit3 = (boundRect[i].br().x > search_lt_x&&boundRect[i].br().x < search_br_x) && (boundRect[i].br().y > search_lt_y&&boundRect[i].br().y < search_br_y); //该矩形右下角在搜索区域内//        //用轮廓的矩形左上角的x右下角的y值代替左下角的值//        int boundRect_bl_x = boundRect[i].tl().x;//        int boundRect_bl_y = boundRect[i].br().y;//        bool limit4 = (boundRect_bl_x > search_lt_x&&boundRect_bl_x < search_br_x) && (boundRect_bl_y > search_lt_y&&boundRect_bl_y < search_br_y);//该矩形右上角在搜索区域内//        if ((limit1 || limit2 || limit3 || limit4)) {//            if (boundRect[i].width < 3 * boundRect[i].height&&boundRect[i].height < 3 * boundRect[i].width) {//去除长条的矩形//                search_area_boundRect[search_rect_count++] = boundRect[i];//                rectangle(result, boundRect[i], Scalar(0, 255, 0), 2);//            }//        }//        rectangle(result, search_Rect, Scalar(255, 0, 0), 2);//在result上绘制正外接搜索矩形框 //        //rectangle(result, boundRect[i], Scalar(0, 255, 0), 2);//在result上绘制正外接矩形//    }//}//在的轮廓矩形search_area_boundRect中寻找最大面积矩形Rect max_Rect = Rect(Point(0, 0), Point(0, 0));double max_area = -1;//防止面积为0的矩形检测不出for (int i = 0; i < search_rect_count; i++) {if (search_area_boundRect[i].area() > max_area) {max_Rect = search_area_boundRect[i];//找出最大矩形max_area = search_area_boundRect[i].area();}}//vector<Rect> select_boundRect(contours.size());//在搜索区域内的轮廓矩形中挑选出离最大矩形较近的矩形 100//int select_boundRect_count = 0;//int maxRect_x = max_Rect.tl().x + max_Rect.height / 2, maxRect_y = max_Rect.tl().y + max_Rect.width / 2;//中心点(最大矩形的重心)//for (int i = 0; i < search_rect_count; i++) {//    int distance;//两矩形中心点求距离//    int x = (search_area_boundRect[i].tl().x + search_area_boundRect[i].br().x) / 2, y = (search_area_boundRect[i].tl().y + search_area_boundRect[i].br().y) / 2;//遍历矩形的重心//    distance = (maxRect_x - x)*(maxRect_x - x) + (maxRect_y - y)*(maxRect_y - y);//    //if (distance <= 10000 * 1.0 / (shrink*shrink)) {//    select_boundRect[select_boundRect_count++] = search_area_boundRect[i];//挑出到最大矩形重心距离小于100/16的矩形////}//}//int min_x = 2000, min_y = 2000, max_x = 0, max_y = 0;//找到左上角和右下角的坐标//for (int i = 0; i < select_boundRect_count; i++) {//    if (select_boundRect[i].tl().x < min_x) {//        min_x = select_boundRect[i].tl().x;//最小x值//    }if (select_boundRect[i].tl().y < min_y) {//        min_y = select_boundRect[i].tl().y;//最小y值//    }//    if (select_boundRect[i].br().x > max_x) {//        max_x = select_boundRect[i].br().x;//    }//    if (select_boundRect[i].br().y > max_y) {//        max_y = select_boundRect[i].br().y;//    }//    //rectangle(result, select_boundRect[i], Scalar(0, 255, 0), 2);//在result上绘制正外接矩形 //}////最大矩形合并周围矩形//Rect draw_Rect = Rect(Point(min_x, min_y), Point(max_x, max_y));//if (min_x == 2000 || min_y == 2000 || max_x == 0 || max_y == 0) {//    draw_Rect = pre_Rect;//物体静止时 将之前的矩形赋给当前矩形//}
Rect draw_Rect;draw_Rect = max_Rect;double centers_distance = getDistance(getCenterPoint(draw_Rect), getCenterPoint(pre_Rect));//这一帧框和上一帧框两中心点间的距离double diagonal = getDistance(max_Rect.tl(), max_Rect.br());//当前框的对角线的距离if (max_Rect.area() == 0 || centers_distance > diagonal) {draw_Rect = pre_Rect;}//防止孤立点出现或者框过小if (draw_Rect.width < 40) {draw_Rect = Rect(Point(draw_Rect.tl().x - (40 - draw_Rect.width) / 2, draw_Rect.tl().y), Point(draw_Rect.br().x + (40 - draw_Rect.width) / 2, draw_Rect.br().y));}if (draw_Rect.height < 20) {draw_Rect = Rect(Point(draw_Rect.tl().x, draw_Rect.tl().y - (20 - draw_Rect.height) / 2), Point(draw_Rect.br().x, draw_Rect.br().y + (draw_Rect.height) / 2));}pre_Rect = draw_Rect;rectangle(result, draw_Rect, Scalar(0, 0, 255), 2);//在result上绘制正外接矩形  return result;//返回result
}
//求矩形框的中心点
Point getCenterPoint(Rect rect) {Point cpt;cpt.x = rect.x + cvRound(rect.width / 2.0);//cvRound四舍五入cpt.y = rect.y + cvRound(rect.height / 2.0);return cpt;
}
//求两点之间的距离
double getDistance(Point p1, Point p2) {return sqrt(pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2));
}void onMouse(int event, int x, int y, int, void *) {if (event == CV_EVENT_LBUTTONDOWN) {pre_Rect.x = x;pre_Rect.y = y;}else if (event == CV_EVENT_LBUTTONUP) {pre_Rect.width = x - pre_Rect.x;pre_Rect.height = y - pre_Rect.y;}
}

缺点:

1.不能够达到实时检测 在背景简单时每秒检测大概20-30帧 更简单背景时也能达到30帧以上,但背景复杂时每秒仅为3-4帧

2.视频图片前后帧的拼接结果好坏直接影响最终的无人机定位效果

3.如果跟踪框丢失 再次找回具有偶然性 只有当目标再次落入搜索框内才可能再次进行跟踪

转载于:https://www.cnblogs.com/henuLiGang/p/10281256.html

无人机目标定位C++程序相关推荐

  1. 【新无人机数据集】从 行人重识别 到 无人机目标定位

    论文题目:University-1652: A Multi-view Multi-source Benchmark for Drone-based Geo-localization 论文地址:http ...

  2. 【新无人机数据集】从行人重识别 到 无人机目标定位

    点击我爱计算机视觉标星,更快获取CVML新技术 本文原载于知乎,已获作者授权转载,请勿二次转载. https://zhuanlan.zhihu.com/p/110987552 简介(与行人重识别的关系 ...

  3. 无人机光电吊舱目标定位

    @无人机光电吊舱目标定位TOC 参考论文<一种基于KL-AEPF的无人机侦察移动目标定位算法>了解目标定位需要用到的坐标系 这篇论文这部分讲的不错! /*<一种基于KL-AEPF的无 ...

  4. 无人机光电吊舱目标定位-实验安排

    1.采用安卓(Android)和苹果(iOS)系统采集不同点的GPS信息 (实验一) 下图是采用安卓系统采集的GPS信息 lon=114.422868 lat=30.453983 high=65.33 ...

  5. 3.1 目标定位-深度学习第四课《卷积神经网络》-Stanford吴恩达教授

    ←上一篇 ↓↑ 下一篇→ 2.12 总结 回到目录 3.2 特征点检测 目标定位 (Object Localization) 大家好,欢迎回来,这一周我们学习的主要内容是对象检测,它是计算机视觉领域中 ...

  6. 基于单目视觉的平面目标定位和坐标测量 (下) - 相机姿态估计和目标测量

    上回说到,我们回顾了机器视觉的基础知识,然后一顿操作之后得到了相机内参A和畸变系数dist. 现在我们开始定位目标的坐标. 这个过程包括几个子部分: 1.    标记检测 2.    指定世界坐标系, ...

  7. 清华大学课题组联合美团研发无人机声波定位技术获ACM SenSys顶会大奖

    11月6日至9日,第20届国际计算机学会(Association for Computing Machinery,简称ACM)嵌入式网络感知系统大会(Conference on Embedded Ne ...

  8. 目标定位(Object localization)

    来源:Coursera吴恩达深度学习课程 在构建目标检测之前,建议先了解一下目标定位(object localization). 在上图的这个例子中,图片分类(image classification ...

  9. 使用BREW开发定位应用程序

    介绍        本文目的是给那些BREW开发者们一个关于BREW SDK/API中有效特征的大概的了解,他们用这些来创建BREW定位应用程序. gpsOne gpsOne是一种混合定位系统.包括A ...

最新文章

  1. daterangepicker引用
  2. 判断按键值_「正点原子NANO STM32开发板资料连载」第十六章电容触摸按键实验...
  3. Unity3d--美工建模须知【转http://blog.csdn.net/tanmengwen/article/details/8735889】
  4. 关于JavaWeb项目加密的实现 2021-04-24
  5. 【BP数据预测】基于matlab蝙蝠算法优化BP神经网络数据预测【含Matlab源码 1379期】
  6. 扒一扒贝索斯的接班人,为何选他挑起大梁?
  7. hrm系统源码php,悟空HRM下载_悟空HRM0.1开源版 - 系统之家
  8. 计算机操作系统的自举过程
  9. 2022爱分析· 工业互联网厂商全景报告
  10. qt 在ubuntu下的下载安装及测试
  11. 打造舒适搬砖环境,这些是我最想推介的桌面好物
  12. 魅族容器云平台基于Kubernetes自动化运维实践
  13. ipmi 的初始化,其作用是和BMC通信
  14. 基于SSM实现的物流管理系统【附源码】(毕设)
  15. 常用的计算机杀毒软件图标,杀毒软件都有哪些,它们的图标是什么样子的?
  16. Mysql 面试题总结
  17. 好分数阅卷3.0_好分数阅卷3.0app
  18. 如何解决Visual Studio2010 编译时提示系统找不到指定文件问题
  19. useSSL是什么意思
  20. Bootstrap导航栏下拉菜单鼠标滑过展开

热门文章

  1. 程序员需要学习太多数学知识吗?
  2. 还不会python面相对象?活该单身(面向对象基础+交互关系)
  3. 深度学习(六十)网络压缩简单总结
  4. pycharm入门的简易使用教程
  5. 游戏会记录某个api的调用_专家坐诊丨老出BUG怎么办?游戏服务器常见问题的解决方法分享...
  6. java自动获取ip_java自动获取电脑ip和MAC地址
  7. python删除数据库_用Python删除Cosmos数据库文档
  8. 2019年网络规划设计师上午真题及答案解析
  9. 32f4 usb 升级程序_不断中招的你还放心升级win10吗?wi10近期更新问题及解决办法...
  10. 【GPU加速系列】PyCUDA(一):上手简单操作