您的位置:首页 > 其它

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

2015-12-27 22:33 447 查看

目录

目录

说明

程序代码
1 代码说明

2 代码使用说明

运行截图

问题与解决方法

接下来

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的东西不可避免的要稍微搁一下了,有时间再把双目视觉的我的理解,和一些代码传上来备份一下。

更多光流算法,可见我之前的文章: /article/7582892.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: