ROSRUN ros cpp 相机节点创建
ROSRUN ros cpp node creation for camera
我已经有了一个 catkin_ws
工作区,其中有一些 ros 节点和主题,所有这些都可以让相机连接到它,这意味着相机与这些节点接合,我有一个 cpp 可以与拍摄相机一起运行作为输入,而 运行 只喜欢 ./example -camera
,其中没有任何 ros 编码。
现在我想将通用 example.cpp
转换为 ros cpp whicenter 代码在这里做 ros::init()
并订阅已经 运行 的相机并实时提供输出视频。
我想了解整个事情,但我不知道如何从已经 运行 的节点获取摄像头视频,这意味着我想要 rosrun 文件,它在运行时拍摄摄像头。
cv::VideoCapture video;
bool useCamera = true;
if( useCamera )
video.open(0);
#include <opencv/cv.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <math.h>
#include <stdio.h>
#include <iostream>
#include <time.h>
#include "../src/MSAC.h"
#include "../src/pedro.cpp"
using namespace std;
using namespace cv;
int uheight = 240;
int uwidth = 320;
int vthres = 60;
Size size(uwidth, uheight);
cv::Mat inputImg;
// std::vector<cv::Mat> vps; // vector of vps: vps[vpNum], with vpNum=0...numDetectedVps
//it takes the label number which you want as output
Mat labelled_image(int label,int *arr_label[],Mat image)
{
Mat temp(image.size(),CV_8UC1,Scalar(0));
for(int i=0;i<image.rows;i++)
{
for(int j=0;j<image.cols;j++)
{
if(label==arr_label[i][j])
{
temp.at<uchar>(i,j)=255;
}
}
}
return(temp);
}
void help()
{
cout << "/*\n"
<< " **************************************************************************************************\n"
<< " * Vanishing point detection using Hough and MSAC \n"
<< " * ----------------------------------------------------\n"
<< " * \n"
<< " * Author:Marcos Nieto\n"
<< " * www.marcosnieto.net\n"
<< " * marcos.nieto.doncel@gmail.com\n"
<< " * \n"
<< " * Date:01/12/2011\n"
<< " **************************************************************************************************\n"
<< " * \n"
<< " * Usage: \n"
<< " * -numVps # Number of vanishing points to detect (at maximum) \n"
<< " * -mode # Estimation mode (default is NIETO): LS (Least Squares), NIETO\n"
<< " * -video # Specifies video file as input (if not specified, camera is used) \n"
<< " * -image # Specifies image file as input (if not specified, camera is used) \n"
<< " * -verbose # Actives verbose: ON, OFF (default)\n"
<< " * -play # ON: the video runs until the end; OFF: frame by frame (key press event)\n"
<< " * -resizedWidth # Specifies the desired width of the image (the height is computed to keep aspect ratio)\n"
<< " * Example:\n"
<< " * vanishingPoint.exe -numVps 2 -video myVideo.avi -verbose ON\n"
<< " * vanishingPoint.exe -numVps 2 -image myImage.jpg\n"
<< " * vanishingPoint.exe -numVps 1 -play OFF -resizedWidth 640\n"
<< " * \n"
<< " * Keys:\n"
<< " * Esc: Quit\n"
<< " */\n" << endl;
}
/** This function contains the actions performed for each image*/
void processImage(MSAC &msac, int numVps, cv::Mat &imgGRAY, cv::Mat &outputImg)
{
cv::Mat imgCanny;
// Canny
cv::Canny(imgGRAY, imgCanny, 40, 65, 3);
// Hough
vector<vector<cv::Point> > lineSegments;
vector<cv::Point> aux;
#ifndef USE_PPHT
vector<Vec2f> lines;
cv::HoughLines( imgCanny, lines, 1, CV_PI/180, 130);
for(size_t i=0; i< lines.size(); i++)
{
float rho = lines[i][0];
float theta = lines[i][1];
double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho;
Point pt1, pt2;
pt1.x = cvRound(x0 + 1000*(-b));
pt1.y = cvRound(y0 + 1000*(a));
pt2.x = cvRound(x0 - 1000*(-b));
pt2.y = cvRound(y0 - 1000*(a));
aux.clear();
aux.push_back(pt1);
aux.push_back(pt2);
lineSegments.push_back(aux);
line(outputImg, pt1, pt2, CV_RGB(0, 0, 0), 1, 8);
}
#else
vector<Vec4i> lines;
int houghThreshold = 70;
if(imgGRAY.cols*imgGRAY.rows < 400*400)
houghThreshold = 100;
cv::HoughLinesP(imgCanny, lines, 1, CV_PI/180, houghThreshold, 10,10);
while(lines.size() > MAX_NUM_LINES)
{
lines.clear();
houghThreshold += 10;
cv::HoughLinesP(imgCanny, lines, 1, CV_PI/180, houghThreshold, 10, 10);
}
for(size_t i=0; i<lines.size(); i++)
{
Point pt1, pt2;
pt1.x = lines[i][0];
pt1.y = lines[i][1];
pt2.x = lines[i][2];
pt2.y = lines[i][3];
line(outputImg, pt1, pt2, CV_RGB(0,0,0), 2);
/*circle(outputImg, pt1, 2, CV_RGB(255,255,255), CV_FILLED);
circle(outputImg, pt1, 3, CV_RGB(0,0,0),1);
circle(outputImg, pt2, 2, CV_RGB(255,255,255), CV_FILLED);
circle(outputImg, pt2, 3, CV_RGB(0,0,0),1);*/
// Store into vector of pairs of Points for msac
aux.clear();
aux.push_back(pt1);
aux.push_back(pt2);
lineSegments.push_back(aux);
}
#endif
// Multiple vanishing points
std::vector<cv::Mat> vps; // vector of vps: vps[vpNum], with vpNum=0...numDetectedVps
std::vector<std::vector<int> > CS; // index of Consensus Set for all vps: CS[vpNum] is a vector containing indexes of lineSegments belonging to Consensus Set of vp numVp
std::vector<int> numInliers;
std::vector<std::vector<std::vector<cv::Point> > > lineSegmentsClusters;
// Call msac function for multiple vanishing point estimation
msac.multipleVPEstimation(lineSegments, lineSegmentsClusters, numInliers, vps, numVps);
for(int v=0; v<vps.size(); v++)
{
printf("VP %d (%.3f, %.3f, %.3f)", v, vps[v].at<float>(0,0), vps[v].at<float>(1,0), vps[v].at<float>(2,0));
fflush(stdout);
double vpNorm = cv::norm(vps[v]);
if(fabs(vpNorm - 1) < 0.001)
{
printf("(INFINITE)");
fflush(stdout);
}
printf("\n");
}
// Draw line segments according to their cluster
msac.drawCS(outputImg, lineSegmentsClusters, vps);
// View
namedWindow("Output", CV_WINDOW_KEEPRATIO);
imshow("Output", outputImg);
// imwrite("vanishingPoint.jpg", outputImg);
// storing 'y' values of vanishing point and getting that 'y' value till which we will do processing on our image
float one, two = 0.0;
int x1, x2 = 1;
vthres = 60;
int tmax = uheight-120;
if(vps.size() == 1)
{
x1 = vps[0].at<float>(0,0);
if(x1 > 0 && x1 < uwidth){
one = vps[0].at<float>(0,1);
if(one <0) one = vthres;
if(one > tmax) vthres = tmax;
else vthres = one;
}
}
else if(vps.size() == 2)
{
x1 = vps[0].at<float>(0,0);
x2 = vps[1].at<float>(0,0);
if(x1 > 0 && x1 < uwidth)
{
one = vps[0].at<float>(0,1);
if(one <0) one = vthres;
}
else one = vthres;
if(x2 > 0 && x2 < uwidth)
{
two = vps[1].at<float>(0,1);
if(two<0) two = vthres;
}
else two = vthres;
if(one > tmax && two > tmax) vthres = tmax;
else if(one > tmax || two > tmax) vthres = (one > two) ? two : one;
else vthres = (one > two) ? one : two;
}
else vthres = vthres;
cout << "\nvanishing point: " << vthres << endl;
// Resizing image considering vanishing point
Mat img(inputImg, Rect(0,vthres,uwidth,uheight-vthres) );
// resize(img,img,size);
cout << "\nUpdated Image size: (" << img.cols << " x " << img.rows << ')' << endl;
/*Result of graph-segmentation*/
cv::Mat output(img.size(),img.type());
/*labelled image i.e each segment is assigned a particular label*/
cv::Mat label_image(img.size(),img.type(),Scalar(0));
/*Parameters for graph-segmentation*/
int k = 800;
int min_size = 50;
pedro p = pedro(img, k, min_size);
// cv::imshow("input image",img);
p.Evaluate();
cout<<"number of segments = "<<p.num_ccs<<endl;
p.output_seg.copyTo(output);
namedWindow(" segmented output ",CV_WINDOW_KEEPRATIO);
cv::imshow(" segmented output ",output);
// imwrite("segmented.jpg", output);
/**Suppose you want to check a segment number then uncomment the code below and provide
* the label number**/
// Storing labels in a Mat object labels
Mat labels(img.size(),CV_8UC1,Scalar(0));
for(int i=0;i<img.rows;i++){
for(int j=0;j<img.cols;j++){
labels.at<uchar>(i,j) = p.labels_seg[i][j];
}
}
// detecting road label
float total = 0.0;
Mat label1(labels, Rect(100, uheight-vthres-15, 150, 15));
Mat label2(labels, Rect(110, uheight-vthres-20, 120, 20));
Mat label3(labels, Rect(120, uheight-vthres-30, 80, 30));
total = ((sum(label1)[0] / 2250) + (sum(label2)[0] / 2400) + (sum(label3)[0] / 2400)) / 3;
// total = ceil(total);
int label_no = total;
cout << "\nlabel: " << label_no << "\ttotal: " << total << endl;
label_image = labelled_image(label_no, p.labels_seg, img); //Suppose you want label 1
cv::namedWindow("labelimage", CV_WINDOW_KEEPRATIO);
cv::imshow("labelimage",label_image);
// imwrite("boundary.jpg", label_image);
// Find contours
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
RNG rng(12345);
findContours( label_image, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
// Draw contours
Mat drawing = Mat::zeros( label_image.size(), CV_8UC3 );
for( int i = 0; i< contours.size(); i++ )
{
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );
}
// display contours
namedWindow("Contours", CV_WINDOW_KEEPRATIO);
imshow("Contours", drawing);
// imwrite("drawing.jpg", drawing);
// vector for boundary points
vector<int>bdp;
// finding boundary points
for(int i= 0; i < contours.size(); i++)
{
for(int j= 0; j < contours[i].size();j++) // run until j < contours[i].size();
{
if(contours[i][j].y == uheight-vthres-2){
bdp.push_back(contours[i][j].x);
}
}
}
// sdist is safe-distance
int right,left=0;
int sdist = 10;
for(int i=0; i < bdp.size(); i++)
{
cout << "\nCorner Point: (" << bdp[i] << ", " << uheight-vthres-2 << ")" << endl;
if(bdp[i]-(uwidth/2) > 0) right = bdp[i]- (uwidth/2) -sdist;
else left = -1 * ((uwidth/2) - bdp[i] - sdist);
}
// displaying boundary distances
cout << "\nLeft Distance: " << left << "\tRight Distance: " << right << endl;
}
int main(int argc, char** argv)
{
// time starts now
clock_t tStart = clock();
// Images
Mat imgGRAY;
Mat outputImg;
// Other variables
char *videoFileName = 0;
char *imageFileName = 0;
cv::VideoCapture video;
bool useCamera = true;
int mode = MODE_NIETO;
int numVps = 1;
bool playMode = true;
bool stillImage = false;
bool verbose = false;
int procWidth = -1;
int procHeight = -1;
cv::Size procSize;
// Start showing help
// help();
// Parse arguments
if(argc < 2)
return -1;
for(int i=1; i<argc; i++)
{
const char* s = argv[i];
if(strcmp(s, "-video" ) == 0)
{
// Input video is a video file
videoFileName = argv[++i];
useCamera = false;
}
else if(strcmp(s,"-image") == 0)
{
// Input is a image file
imageFileName = argv[++i];
stillImage = true;
useCamera = false;
}
else if(strcmp(s, "-resizedWidth") == 0)
{
procWidth = atoi(argv[++i]);
}
else if(strcmp(s, "-verbose" ) == 0)
{
const char* ss = argv[++i];
if(strcmp(ss, "ON") == 0 || strcmp(ss, "on") == 0
|| strcmp(ss, "TRUE") == 0 || strcmp(ss, "true") == 0
|| strcmp(ss, "YES") == 0 || strcmp(ss, "yes") == 0 )
verbose = true;
}
else if(strcmp(s, "-play" ) == 0)
{
const char* ss = argv[++i];
if(strcmp(ss, "OFF") == 0 || strcmp(ss, "off") == 0
|| strcmp(ss, "FALSE") == 0 || strcmp(ss, "false") == 0
|| strcmp(ss, "NO") == 0 || strcmp(ss, "no") == 0
|| strcmp(ss, "STEP") == 0 || strcmp(ss, "step") == 0)
playMode = false;
}
else if(strcmp(s, "-mode" ) == 0)
{
const char* ss = argv[++i];
if(strcmp(ss, "LS") == 0)
mode = MODE_LS;
else if(strcmp(ss, "NIETO") == 0)
mode = MODE_NIETO;
else
{
perror("ERROR: Only LS or NIETO modes are supported\n");
}
}
else if(strcmp(s,"-numVps") == 0)
{
numVps = atoi(argv[++i]);
}
}
// Open video input
if( useCamera )
video.open(0);
else
{
if(!stillImage)
// video.open(videoFileName);
video = VideoCapture(videoFileName);
}
// Check video input
int width = 0, height = 0, fps = 0, fourcc = 0;
if(!stillImage)
{
if( !video.isOpened() )
{
printf("ERROR: can not open camera or video file\n");
return -1;
}
else
{
// Show video information
width = (int) video.get(CV_CAP_PROP_FRAME_WIDTH);
height = (int) video.get(CV_CAP_PROP_FRAME_HEIGHT);
fps = (int) video.get(CV_CAP_PROP_FPS);
fourcc = (int) video.get(CV_CAP_PROP_FOURCC);
if(!useCamera)
printf("Input video: (%d x %d) at %d fps, fourcc = %d\n", width, height, fps, fourcc);
else
printf("Input camera: (%d x %d) at %d fps\n", width, height, fps);
}
}
else
{
inputImg = cv::imread(imageFileName);
if(inputImg.empty())
return -1;
resize(inputImg,inputImg,size);
// size of image
width = inputImg.cols;
height = inputImg.rows;
printf("Input image: (%d x %d)\n", width, height);
playMode = false;
}
// Resize
if(procWidth != -1)
{
procHeight = height*((double)procWidth/width);
procSize = cv::Size(procWidth, procHeight);
printf("Resize to: (%d x %d)\n", procWidth, procHeight);
}
else
procSize = cv::Size(width, height);
// Create and init MSAC
MSAC msac;
msac.init(mode, procSize, verbose);
int frameNum=0;
for( ;; )
{
if(!stillImage)
{
printf("\n-------------------------\nFRAME #%6d\n", frameNum);
frameNum++;
// Get current image
video >> inputImg;
}
if( inputImg.empty() )
break;
resize(inputImg,inputImg,size);
// Resize to processing size
// cv::resize(inputImg, inputImg, procSize);
// Color Conversion
if(inputImg.channels() == 3)
{
cv::cvtColor(inputImg, imgGRAY, CV_BGR2GRAY);
inputImg.copyTo(outputImg);
}
else
{
inputImg.copyTo(imgGRAY);
cv::cvtColor(inputImg, outputImg, CV_GRAY2BGR);
}
// ++++++++++++++++++++++++++++++++++++++++
// Process
// ++++++++++++++++++++++++++++++++++++++++
processImage(msac, numVps, imgGRAY, outputImg);
printf("Time taken: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
if(playMode)
cv::waitKey(1);
else
cv::waitKey(0);
char q = (char)waitKey(1);
if( q == 27 )
{
printf("\nStopped by user request\n");
break;
}
if(stillImage)
break;
}
if(!stillImage)
video.release();
return 0;
}
你必须做的第一件事是:
ros::init(argc, argv, "Nome_of_the_node"); //This is to initialize ros
ros::NodeHandle nh;
这是该节点的节点句柄,可用于发布、订阅主题以及从文件中获取参数。在你的 main 的最后几行你必须写:
ros::spin();
这将使您的节点保持活动状态,并且它将在新消息到达时更新每个回调。
下一步,您想从 运行 摄像头获取视频。为此,您必须订阅相机发布的主题。您可以通过在终端 rostopic list
上书写来找到该主题。当您找到正确的主题时,您必须写 rostopic info topic_name
。这将为您提供相机在该节点上发布的消息类型。假设是sensor_msgs/Image
。之后,在你的 cpp 中,你必须将你的节点订阅到该主题:
ros::Subscriber sub = nh.subscribe<sensor_msgs::Image>("topic_name", num_message_in_queue, callbackname);
然后你必须创建这个回调:
void callbackname(const sensor_msgs::Image::ConstPtr& msg)
其中 msg 将包含您的视频图像。
如需进一步参考,我建议您阅读本教程:http://wiki.ros.org/ROS/Tutorials
我已经有了一个 catkin_ws
工作区,其中有一些 ros 节点和主题,所有这些都可以让相机连接到它,这意味着相机与这些节点接合,我有一个 cpp 可以与拍摄相机一起运行作为输入,而 运行 只喜欢 ./example -camera
,其中没有任何 ros 编码。
现在我想将通用 example.cpp
转换为 ros cpp whicenter 代码在这里做 ros::init()
并订阅已经 运行 的相机并实时提供输出视频。
我想了解整个事情,但我不知道如何从已经 运行 的节点获取摄像头视频,这意味着我想要 rosrun 文件,它在运行时拍摄摄像头。
cv::VideoCapture video;
bool useCamera = true;
if( useCamera )
video.open(0);
#include <opencv/cv.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <math.h>
#include <stdio.h>
#include <iostream>
#include <time.h>
#include "../src/MSAC.h"
#include "../src/pedro.cpp"
using namespace std;
using namespace cv;
int uheight = 240;
int uwidth = 320;
int vthres = 60;
Size size(uwidth, uheight);
cv::Mat inputImg;
// std::vector<cv::Mat> vps; // vector of vps: vps[vpNum], with vpNum=0...numDetectedVps
//it takes the label number which you want as output
Mat labelled_image(int label,int *arr_label[],Mat image)
{
Mat temp(image.size(),CV_8UC1,Scalar(0));
for(int i=0;i<image.rows;i++)
{
for(int j=0;j<image.cols;j++)
{
if(label==arr_label[i][j])
{
temp.at<uchar>(i,j)=255;
}
}
}
return(temp);
}
void help()
{
cout << "/*\n"
<< " **************************************************************************************************\n"
<< " * Vanishing point detection using Hough and MSAC \n"
<< " * ----------------------------------------------------\n"
<< " * \n"
<< " * Author:Marcos Nieto\n"
<< " * www.marcosnieto.net\n"
<< " * marcos.nieto.doncel@gmail.com\n"
<< " * \n"
<< " * Date:01/12/2011\n"
<< " **************************************************************************************************\n"
<< " * \n"
<< " * Usage: \n"
<< " * -numVps # Number of vanishing points to detect (at maximum) \n"
<< " * -mode # Estimation mode (default is NIETO): LS (Least Squares), NIETO\n"
<< " * -video # Specifies video file as input (if not specified, camera is used) \n"
<< " * -image # Specifies image file as input (if not specified, camera is used) \n"
<< " * -verbose # Actives verbose: ON, OFF (default)\n"
<< " * -play # ON: the video runs until the end; OFF: frame by frame (key press event)\n"
<< " * -resizedWidth # Specifies the desired width of the image (the height is computed to keep aspect ratio)\n"
<< " * Example:\n"
<< " * vanishingPoint.exe -numVps 2 -video myVideo.avi -verbose ON\n"
<< " * vanishingPoint.exe -numVps 2 -image myImage.jpg\n"
<< " * vanishingPoint.exe -numVps 1 -play OFF -resizedWidth 640\n"
<< " * \n"
<< " * Keys:\n"
<< " * Esc: Quit\n"
<< " */\n" << endl;
}
/** This function contains the actions performed for each image*/
void processImage(MSAC &msac, int numVps, cv::Mat &imgGRAY, cv::Mat &outputImg)
{
cv::Mat imgCanny;
// Canny
cv::Canny(imgGRAY, imgCanny, 40, 65, 3);
// Hough
vector<vector<cv::Point> > lineSegments;
vector<cv::Point> aux;
#ifndef USE_PPHT
vector<Vec2f> lines;
cv::HoughLines( imgCanny, lines, 1, CV_PI/180, 130);
for(size_t i=0; i< lines.size(); i++)
{
float rho = lines[i][0];
float theta = lines[i][1];
double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho;
Point pt1, pt2;
pt1.x = cvRound(x0 + 1000*(-b));
pt1.y = cvRound(y0 + 1000*(a));
pt2.x = cvRound(x0 - 1000*(-b));
pt2.y = cvRound(y0 - 1000*(a));
aux.clear();
aux.push_back(pt1);
aux.push_back(pt2);
lineSegments.push_back(aux);
line(outputImg, pt1, pt2, CV_RGB(0, 0, 0), 1, 8);
}
#else
vector<Vec4i> lines;
int houghThreshold = 70;
if(imgGRAY.cols*imgGRAY.rows < 400*400)
houghThreshold = 100;
cv::HoughLinesP(imgCanny, lines, 1, CV_PI/180, houghThreshold, 10,10);
while(lines.size() > MAX_NUM_LINES)
{
lines.clear();
houghThreshold += 10;
cv::HoughLinesP(imgCanny, lines, 1, CV_PI/180, houghThreshold, 10, 10);
}
for(size_t i=0; i<lines.size(); i++)
{
Point pt1, pt2;
pt1.x = lines[i][0];
pt1.y = lines[i][1];
pt2.x = lines[i][2];
pt2.y = lines[i][3];
line(outputImg, pt1, pt2, CV_RGB(0,0,0), 2);
/*circle(outputImg, pt1, 2, CV_RGB(255,255,255), CV_FILLED);
circle(outputImg, pt1, 3, CV_RGB(0,0,0),1);
circle(outputImg, pt2, 2, CV_RGB(255,255,255), CV_FILLED);
circle(outputImg, pt2, 3, CV_RGB(0,0,0),1);*/
// Store into vector of pairs of Points for msac
aux.clear();
aux.push_back(pt1);
aux.push_back(pt2);
lineSegments.push_back(aux);
}
#endif
// Multiple vanishing points
std::vector<cv::Mat> vps; // vector of vps: vps[vpNum], with vpNum=0...numDetectedVps
std::vector<std::vector<int> > CS; // index of Consensus Set for all vps: CS[vpNum] is a vector containing indexes of lineSegments belonging to Consensus Set of vp numVp
std::vector<int> numInliers;
std::vector<std::vector<std::vector<cv::Point> > > lineSegmentsClusters;
// Call msac function for multiple vanishing point estimation
msac.multipleVPEstimation(lineSegments, lineSegmentsClusters, numInliers, vps, numVps);
for(int v=0; v<vps.size(); v++)
{
printf("VP %d (%.3f, %.3f, %.3f)", v, vps[v].at<float>(0,0), vps[v].at<float>(1,0), vps[v].at<float>(2,0));
fflush(stdout);
double vpNorm = cv::norm(vps[v]);
if(fabs(vpNorm - 1) < 0.001)
{
printf("(INFINITE)");
fflush(stdout);
}
printf("\n");
}
// Draw line segments according to their cluster
msac.drawCS(outputImg, lineSegmentsClusters, vps);
// View
namedWindow("Output", CV_WINDOW_KEEPRATIO);
imshow("Output", outputImg);
// imwrite("vanishingPoint.jpg", outputImg);
// storing 'y' values of vanishing point and getting that 'y' value till which we will do processing on our image
float one, two = 0.0;
int x1, x2 = 1;
vthres = 60;
int tmax = uheight-120;
if(vps.size() == 1)
{
x1 = vps[0].at<float>(0,0);
if(x1 > 0 && x1 < uwidth){
one = vps[0].at<float>(0,1);
if(one <0) one = vthres;
if(one > tmax) vthres = tmax;
else vthres = one;
}
}
else if(vps.size() == 2)
{
x1 = vps[0].at<float>(0,0);
x2 = vps[1].at<float>(0,0);
if(x1 > 0 && x1 < uwidth)
{
one = vps[0].at<float>(0,1);
if(one <0) one = vthres;
}
else one = vthres;
if(x2 > 0 && x2 < uwidth)
{
two = vps[1].at<float>(0,1);
if(two<0) two = vthres;
}
else two = vthres;
if(one > tmax && two > tmax) vthres = tmax;
else if(one > tmax || two > tmax) vthres = (one > two) ? two : one;
else vthres = (one > two) ? one : two;
}
else vthres = vthres;
cout << "\nvanishing point: " << vthres << endl;
// Resizing image considering vanishing point
Mat img(inputImg, Rect(0,vthres,uwidth,uheight-vthres) );
// resize(img,img,size);
cout << "\nUpdated Image size: (" << img.cols << " x " << img.rows << ')' << endl;
/*Result of graph-segmentation*/
cv::Mat output(img.size(),img.type());
/*labelled image i.e each segment is assigned a particular label*/
cv::Mat label_image(img.size(),img.type(),Scalar(0));
/*Parameters for graph-segmentation*/
int k = 800;
int min_size = 50;
pedro p = pedro(img, k, min_size);
// cv::imshow("input image",img);
p.Evaluate();
cout<<"number of segments = "<<p.num_ccs<<endl;
p.output_seg.copyTo(output);
namedWindow(" segmented output ",CV_WINDOW_KEEPRATIO);
cv::imshow(" segmented output ",output);
// imwrite("segmented.jpg", output);
/**Suppose you want to check a segment number then uncomment the code below and provide
* the label number**/
// Storing labels in a Mat object labels
Mat labels(img.size(),CV_8UC1,Scalar(0));
for(int i=0;i<img.rows;i++){
for(int j=0;j<img.cols;j++){
labels.at<uchar>(i,j) = p.labels_seg[i][j];
}
}
// detecting road label
float total = 0.0;
Mat label1(labels, Rect(100, uheight-vthres-15, 150, 15));
Mat label2(labels, Rect(110, uheight-vthres-20, 120, 20));
Mat label3(labels, Rect(120, uheight-vthres-30, 80, 30));
total = ((sum(label1)[0] / 2250) + (sum(label2)[0] / 2400) + (sum(label3)[0] / 2400)) / 3;
// total = ceil(total);
int label_no = total;
cout << "\nlabel: " << label_no << "\ttotal: " << total << endl;
label_image = labelled_image(label_no, p.labels_seg, img); //Suppose you want label 1
cv::namedWindow("labelimage", CV_WINDOW_KEEPRATIO);
cv::imshow("labelimage",label_image);
// imwrite("boundary.jpg", label_image);
// Find contours
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
RNG rng(12345);
findContours( label_image, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
// Draw contours
Mat drawing = Mat::zeros( label_image.size(), CV_8UC3 );
for( int i = 0; i< contours.size(); i++ )
{
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );
}
// display contours
namedWindow("Contours", CV_WINDOW_KEEPRATIO);
imshow("Contours", drawing);
// imwrite("drawing.jpg", drawing);
// vector for boundary points
vector<int>bdp;
// finding boundary points
for(int i= 0; i < contours.size(); i++)
{
for(int j= 0; j < contours[i].size();j++) // run until j < contours[i].size();
{
if(contours[i][j].y == uheight-vthres-2){
bdp.push_back(contours[i][j].x);
}
}
}
// sdist is safe-distance
int right,left=0;
int sdist = 10;
for(int i=0; i < bdp.size(); i++)
{
cout << "\nCorner Point: (" << bdp[i] << ", " << uheight-vthres-2 << ")" << endl;
if(bdp[i]-(uwidth/2) > 0) right = bdp[i]- (uwidth/2) -sdist;
else left = -1 * ((uwidth/2) - bdp[i] - sdist);
}
// displaying boundary distances
cout << "\nLeft Distance: " << left << "\tRight Distance: " << right << endl;
}
int main(int argc, char** argv)
{
// time starts now
clock_t tStart = clock();
// Images
Mat imgGRAY;
Mat outputImg;
// Other variables
char *videoFileName = 0;
char *imageFileName = 0;
cv::VideoCapture video;
bool useCamera = true;
int mode = MODE_NIETO;
int numVps = 1;
bool playMode = true;
bool stillImage = false;
bool verbose = false;
int procWidth = -1;
int procHeight = -1;
cv::Size procSize;
// Start showing help
// help();
// Parse arguments
if(argc < 2)
return -1;
for(int i=1; i<argc; i++)
{
const char* s = argv[i];
if(strcmp(s, "-video" ) == 0)
{
// Input video is a video file
videoFileName = argv[++i];
useCamera = false;
}
else if(strcmp(s,"-image") == 0)
{
// Input is a image file
imageFileName = argv[++i];
stillImage = true;
useCamera = false;
}
else if(strcmp(s, "-resizedWidth") == 0)
{
procWidth = atoi(argv[++i]);
}
else if(strcmp(s, "-verbose" ) == 0)
{
const char* ss = argv[++i];
if(strcmp(ss, "ON") == 0 || strcmp(ss, "on") == 0
|| strcmp(ss, "TRUE") == 0 || strcmp(ss, "true") == 0
|| strcmp(ss, "YES") == 0 || strcmp(ss, "yes") == 0 )
verbose = true;
}
else if(strcmp(s, "-play" ) == 0)
{
const char* ss = argv[++i];
if(strcmp(ss, "OFF") == 0 || strcmp(ss, "off") == 0
|| strcmp(ss, "FALSE") == 0 || strcmp(ss, "false") == 0
|| strcmp(ss, "NO") == 0 || strcmp(ss, "no") == 0
|| strcmp(ss, "STEP") == 0 || strcmp(ss, "step") == 0)
playMode = false;
}
else if(strcmp(s, "-mode" ) == 0)
{
const char* ss = argv[++i];
if(strcmp(ss, "LS") == 0)
mode = MODE_LS;
else if(strcmp(ss, "NIETO") == 0)
mode = MODE_NIETO;
else
{
perror("ERROR: Only LS or NIETO modes are supported\n");
}
}
else if(strcmp(s,"-numVps") == 0)
{
numVps = atoi(argv[++i]);
}
}
// Open video input
if( useCamera )
video.open(0);
else
{
if(!stillImage)
// video.open(videoFileName);
video = VideoCapture(videoFileName);
}
// Check video input
int width = 0, height = 0, fps = 0, fourcc = 0;
if(!stillImage)
{
if( !video.isOpened() )
{
printf("ERROR: can not open camera or video file\n");
return -1;
}
else
{
// Show video information
width = (int) video.get(CV_CAP_PROP_FRAME_WIDTH);
height = (int) video.get(CV_CAP_PROP_FRAME_HEIGHT);
fps = (int) video.get(CV_CAP_PROP_FPS);
fourcc = (int) video.get(CV_CAP_PROP_FOURCC);
if(!useCamera)
printf("Input video: (%d x %d) at %d fps, fourcc = %d\n", width, height, fps, fourcc);
else
printf("Input camera: (%d x %d) at %d fps\n", width, height, fps);
}
}
else
{
inputImg = cv::imread(imageFileName);
if(inputImg.empty())
return -1;
resize(inputImg,inputImg,size);
// size of image
width = inputImg.cols;
height = inputImg.rows;
printf("Input image: (%d x %d)\n", width, height);
playMode = false;
}
// Resize
if(procWidth != -1)
{
procHeight = height*((double)procWidth/width);
procSize = cv::Size(procWidth, procHeight);
printf("Resize to: (%d x %d)\n", procWidth, procHeight);
}
else
procSize = cv::Size(width, height);
// Create and init MSAC
MSAC msac;
msac.init(mode, procSize, verbose);
int frameNum=0;
for( ;; )
{
if(!stillImage)
{
printf("\n-------------------------\nFRAME #%6d\n", frameNum);
frameNum++;
// Get current image
video >> inputImg;
}
if( inputImg.empty() )
break;
resize(inputImg,inputImg,size);
// Resize to processing size
// cv::resize(inputImg, inputImg, procSize);
// Color Conversion
if(inputImg.channels() == 3)
{
cv::cvtColor(inputImg, imgGRAY, CV_BGR2GRAY);
inputImg.copyTo(outputImg);
}
else
{
inputImg.copyTo(imgGRAY);
cv::cvtColor(inputImg, outputImg, CV_GRAY2BGR);
}
// ++++++++++++++++++++++++++++++++++++++++
// Process
// ++++++++++++++++++++++++++++++++++++++++
processImage(msac, numVps, imgGRAY, outputImg);
printf("Time taken: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
if(playMode)
cv::waitKey(1);
else
cv::waitKey(0);
char q = (char)waitKey(1);
if( q == 27 )
{
printf("\nStopped by user request\n");
break;
}
if(stillImage)
break;
}
if(!stillImage)
video.release();
return 0;
}
你必须做的第一件事是:
ros::init(argc, argv, "Nome_of_the_node"); //This is to initialize ros
ros::NodeHandle nh;
这是该节点的节点句柄,可用于发布、订阅主题以及从文件中获取参数。在你的 main 的最后几行你必须写:
ros::spin();
这将使您的节点保持活动状态,并且它将在新消息到达时更新每个回调。
下一步,您想从 运行 摄像头获取视频。为此,您必须订阅相机发布的主题。您可以通过在终端 rostopic list
上书写来找到该主题。当您找到正确的主题时,您必须写 rostopic info topic_name
。这将为您提供相机在该节点上发布的消息类型。假设是sensor_msgs/Image
。之后,在你的 cpp 中,你必须将你的节点订阅到该主题:
ros::Subscriber sub = nh.subscribe<sensor_msgs::Image>("topic_name", num_message_in_queue, callbackname);
然后你必须创建这个回调:
void callbackname(const sensor_msgs::Image::ConstPtr& msg)
其中 msg 将包含您的视频图像。
如需进一步参考,我建议您阅读本教程:http://wiki.ros.org/ROS/Tutorials