【NVIDIA Jetson TK1】四,TK1开发板运行单点光流程序,鼠标点选光流追踪点

目录

1 说明

上一篇文章写了在板子上运行光流,但是这个光流的话是全局的光流,也就是整个屏幕的角点进行光流运算,现在把我之前弄得,一个可选追踪单点的单点式光流程序,整个程序的代码贴出来。

运行环境:
1,nvidia jetson tk1
2.opencv 2.4.9
3.linux 的 g++

2 程序代码

#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <opencv2\opencv.hpp>  
#include <iostream>
#include <ctype.h>
#include <stdio.h>
//#include <unistd.h>
#include <stdlib.h>

using namespace cv;
using namespace std;

vector<Point2f> point1, point2;
bool left_mouse = false;
Point2f point;
int pic_info[4];
Mat gray, prevGray, image;
const Scalar GREEN = Scalar(0, 255, 0);
int rect_width = 0, rect_height = 0;
Point tmpPoint;
static const double pi = 3.14159265358979323846;
static  IplImage *frame1 = NULL;
static IplImage *framet = NULL;
static int line_thickness = 2 ;
CvPoint p, q;

inline static double square(int a)
{
    return a * a;
}

static void onMouse(int event, int x, int y, int /*flags*/, void* /*param*/){
    Mat mouse_show;
    image.copyTo(mouse_show);

    if (event == CV_EVENT_LBUTTONDOWN){
        pic_info[0] = x;
        pic_info[1] = y;
        left_mouse = true;
    }
    else if (event == CV_EVENT_LBUTTONUP){
        rectangle(mouse_show, Point(pic_info[0], pic_info[1]), Point(x, y), GREEN, 2);

        x = (pic_info[0] + x) / 2;
        y = (pic_info[1] + y) / 2;

        point = Point2f((float)x, (float)y);

        point1.clear();
        point2.clear();
        point1.push_back(point);

        imshow("LK Demo", mouse_show);
        left_mouse = false;
    }
    else if ((event == CV_EVENT_MOUSEMOVE) && (left_mouse == true)){
        rectangle(mouse_show, Point(pic_info[0], pic_info[1]), Point(x, y), GREEN, 2);
        imshow("LK Demo", mouse_show);
    }
}

 int main(int argc, char** argv)
{
    //读取摄像头
    VideoCapture cap(0);
    //读取视频文件

    //VideoCapture cap; cap.open("optical_flow_input.avi");
    if (!cap.isOpened())
    {
        return -1;
    }
    TermCriteria termcrit(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.03); //迭代算法的终止条件
    Size winSize(32, 32);
    CvSize frame_size;
    frame_size.height = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
    frame_size.width = cap.get(CV_CAP_PROP_FRAME_WIDTH);
    //allocateOnDemand(&frame1, frame_size, IPL_DEPTH_8U, 3);

    namedWindow("LK Demo", CV_WINDOW_NORMAL);
    setMouseCallback("LK Demo", onMouse, 0);

    for (;;){
        Mat frame;
        cap.read(frame);
        if (frame.empty())
            break;
        frame.copyTo(image);
        cvtColor(image, gray, COLOR_BGR2GRAY);
        framet = &IplImage(image);

        if ((!point1.empty())){
            vector<uchar> status;
            vector<float> err;
            if (prevGray.empty())
                gray.copyTo(prevGray);
            calcOpticalFlowPyrLK(prevGray, gray, point1, point2, status, err, winSize,5, termcrit, 0, 0.001); //使用金字塔Lucas&Kanade方法计算一个稀疏特征集的光流
            tmpPoint = point2[0];

            rectangle(image, Point(tmpPoint.x - 30, tmpPoint.y - 30), Point(tmpPoint.x + 30, tmpPoint.y + 30), GREEN, 2);


            p.x = (int)point1[0].x;
            p.y = (int)point1[0].y;
            q.x = (int)point2[0].x;
            q.y = (int)point2[0].y;

            double angle;
            angle = atan2((double)p.y - q.y, (double)p.x - q.x);
            double hypotenuse;
            hypotenuse = sqrt(square(p.y - q.y) + square(p.x - q.x));

            CvScalar line_color;
            line_color = CV_RGB(255, 0, 0);
            /*执行缩放*/
            q.x = (int)(p.x - 5 * hypotenuse * cos(angle));
            q.y = (int)(p.y - 5 * hypotenuse * sin(angle));

            /*画箭头主线*/
            /* "frame1"要在frame1上作画.
            * "p" 线的开始点.
            * "q" 线的终止点.
            * "CV_AA" 反锯齿.
            * "0" 没有小数位.
            */
            cvLine(framet, p, q, line_color, line_thickness, CV_AA, 0);

            /* 画箭的头部*/
            p.x = (int)(q.x + 9 * cos(angle + pi / 4));
            p.y = (int)(q.y + 9 * sin(angle + pi / 4));
            cvLine(framet, p, q, line_color, line_thickness, CV_AA, 0);
            p.x = (int)(q.x + 9 * cos(angle - pi / 4));
            p.y = (int)(q.y + 9 * sin(angle - pi / 4));
            cvLine(framet, p, q, line_color, line_thickness, CV_AA, 0);

            cvShowImage("LK Demo", framet);
        }

        imshow("LK Demo", image);

        waitKey(100);
        std::swap(point2, point1);
        cv::swap(prevGray, gray);
    }
    return 0;
}

2.1 代码说明

简单说一下这个代码,可以单点光流,因为用的是onmouse()这个函数监视鼠标的事件,鼠标左键单击就会返回一个x,y的坐标值,根据这个点的坐标,输入到光流函数里,光流的部分主要就是靠calcOpticalFlowPyrLK()这个函数实现的,来监视这个点的灰度值在整个过程中的位移变化,并且会移植在这个点周围画一个正方形,移动的速度和方向还用经典的光流向量箭头来表示。

2.2 代码使用说明

在tk1上的使用方法:
1,首先把上面那段代码保存成比如mouse.cpp的文件拷到tk1的某个文件夹位置。
2,然后打开终端,cd进入那个文件夹的位置。
3,在终端中输入

g++ mouse.cpp -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_video -lopencv_contrib  -lopencv_features2d  -lopencv_flann  -lopencv_gpu  -lopencv_legacy  -lopencv_ml   -lopencv_objdetect  -lopencv_photo  -lopencv_stitching  -lopencv_superres  -lopencv_videostab -lopencv_calib3d  -o mouse

4,能跑通的话,cpp文件应该会消失,在该文件夹中出现一个可执行的文件。
5,要运行这个程序的话,两种方式:
一个是接着上面那短代码接着输入

./mouse

这样会在终端中显示运行情况,如果有错误,或者运行不了,在终端中会有错误的提醒。
第二种方式就是直接点击该文件夹里的那个叫mouse的可执行文件,但不会显示运行的情况,只有一个对话框运行着光流代码。

3 运行截图

单点光流运行效果

4 问题与解决方法

问题一:运行时会报内存错误。

解决方法:后来查了一下资料,发现有些函数的接口格式与调用函数时输入进去的格式不符,方法

//先定义一个中间的值
static IplImage *framet = NULL;
//对于原来的值image
mat image;
//用&IplImage()这个小函数转换一下传给暂存值framet 
framet = &IplImage(image);
//之后完美运行
cvShowImage("LK Demo", framet);

问题二:双击可执行文件方式运行程序,程序没法关闭,关了之后还往出冒

解决方法:
首先执行代码:ps -e
调出整个系统的所有进程
看叫 mouse 的这个进程,记住对应的前面四位编号是多少 假设是8888
然后执行 sudo kill 8888
输入密码
进程就结束了,再也不往出冒了

5 接下来

当时弄完这个之后,就开始研究双目视觉的东西,主要就是用两个摄像头来实现对图像深度的测算,目前的进展是:可以完全用一段opencv 的代码在电脑上实现视差图的输出,可以输出指定点的三维坐标,但是三维坐标不是很准,目前怀疑是因为视差图太粗犷缘故,目前在电脑上ok的代码,在tk1上可以编译,但是没法运行,两个摄像头死活启动不起来,目前还没调通。

目前,由于被分配了新的任务,估计opencv的东西不可避免的要稍微搁一下了,有时间再把双目视觉的我的理解,和一些代码传上来备份一下。

更多光流算法,可见我之前的文章: http://blog.csdn.net/hysteric314/article/details/48682327

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值