I have set up ArUco library and now want to write a small code to test if it is working correctly. The code is as below:
#include<opencv2/opencv.hpp>
#include<iostream>
#include<aruco.h>
#include<cvdrawingutils.h>
using namespace cv;
using namespace std;
using namespace aruco;
int main()
{
Mat image;
//Read image and display it
image = imread("E:/../Capture.PNG", 1);
if (image.empty()) //check whether the image is loaded or not
{
cout << "Error : Image cannot be loaded..!!" << endl;
//system("pause"); //wait for a key press
return -1;
}
namedWindow("Image", CV_WINDOW_AUTOSIZE);
imshow("Image", image);
waitKey(1000);
//Marker detection
MarkerDetector MDetector;
vector<Marker> Markers;
//I am not sure if we need to read the pattern of the marker. So I read it.
Markers = imread("E:/.../pattern.PNG", 1);
MDetector.detect(image, Markers);
//draw infor and its boundaries
for (int i = 0; i < Markers.size(); i++)
{
Markers[i].draw(image, Scalar(0, 0, 255), 2);
}
imshow("ouput", image);
waitKey(0);
}
This code builds with zero error, but when I run it, it gives me error.
Error is:
This is what I get when I hit break.
I use Windows 8.1, Microsoft visual studio 2013, opencv 3.0 and ArUco 1.3.0
Any help would be helpful. Thank you very much for help.
This question is solved. I was making use of wrong marker pattern. we are supposed to use the marker pattern provided by ArUco. You can find generate them here: http://terpconnect.umd.edu/~jwelsh12/enes100/markergen.html
There were mistake in the code too. The correct code is below:
#include<opencv2/opencv.hpp>
#include<iostream>
#include<aruco.h>
#include<cvdrawingutils.h>
using namespace cv;
using namespace std;
using namespace aruco;
int main()
{
Mat image;
//Read image and display it
image = imread("E:/Studies/Master Thesis/Markers/arucoTest.PNG", 1);
if (image.empty()) //check whether the image is loaded or not
{
cout << "Error : Image cannot be loaded..!!" << endl;
//system("pause"); //wait for a key press
return -1;
}
namedWindow("Image", CV_WINDOW_AUTOSIZE);
imshow("Image", image);
waitKey(1000);
//Marker detection
MarkerDetector MDetector;
vector<Marker> Markers;
MDetector.detect(image, Markers);
//draw information and its boundaries
for (unsigned int i = 0; i<Markers.size(); i++) {
cout << Markers[i] << endl;
Markers[i].draw(image, Scalar(0, 0, 255), 2);
}
imshow("ouput", image);
waitKey(0);
}
I hope this test code helps newbies to ArUco(others like me).
Related
I meet a problem that one of image from a binocular camera has a time delay corresponding to another image. I use ros package usb-cam to get the images with the time stamps and then use the OpenCV fuction imshow() to show them.
Environment: Ubuntu 16.04 in the Vmware WorkStation 12 (in win10), ROS Kinetic, OpenCV 3.3.0. Binocular camera can support the mjepg format with 640*480 and 30fps.
Well, I am a beginner of vision SLAM and now trying to show images in the real time of a binocular camera. Something I have done is that I have used the usb-cam package to get the image data and shown them in the rviz and rqt. But I meet a time synchroniazation problem with the OpenCV imshow(). Specificlly, I want to use usb-cam to get the data and do some image procession with OpenCV and at first I try to display the images with OpenCV functions.
You will see the codes in the following that I notes some codes.
The code are referred with the open resource project on the github. It is a C++ SLAM project about INS, GPS and binocular camera. I mainly refer the data capture in the rosNodeTest.cpp. It is about a multi-thread coding however I am not familiar with it.
Please visit https://github.com/HKUST-Aerial-Robotics/VINS-Fusion
And there are my codes. It is a ros package and I am sure that it can run well. So there I don't paste the CMakeLists.txt and package.xml.
#include <ros/ros.h>
#include <sensor_msgs/Image.h>
#include <cv_bridge/cv_bridge.h>
#include <opencv2/opencv.hpp>
#include <queue>
#include <thread>
#include <mutex>
#include <iostream>
std::queue<sensor_msgs::ImageConstPtr> img0_buf;
std::queue<sensor_msgs::ImageConstPtr> img1_buf;
std::mutex m_buf;
//Test for rqt, 0 for cv, else for rviz
int flag = 0;
ros::Publisher pubImg0;
ros::Publisher pubImg1;
void img0_callback(const sensor_msgs::ImageConstPtr &img0)
{
m_buf.lock();
//For rqt
if(flag != 0)
{
sensor_msgs::Image img;
img.header=img0->header;
img.height = img0->height;
img.width = img0->width;
img.is_bigendian = img0->is_bigendian;
img.step = img0->step;
img.data=img0->data;
img.encoding=img0->encoding;
pubImg0.publish(img);
// std::cout<<"0."<<img.header<<std::endl;
}
else
{
img0_buf.push(img0);
}
m_buf.unlock();
}
void img1_callback(const sensor_msgs::ImageConstPtr &img1)
{
m_buf.lock();
if(flag != 0)
{
sensor_msgs::Image img;
img.header=img1->header;
img.height = img1->height;
img.width = img1->width;
img.is_bigendian = img1->is_bigendian;
img.step = img1->step;
img.data=img1->data;
img.encoding=img1->encoding;
pubImg1.publish(img);
// std::cout<<"1."<<img.header<<std::endl;
}
else
{
img1_buf.push(img1);
}
m_buf.unlock();
}
//Use the cv_bridge of ros to change the image data format from msgs to cv
cv::Mat msg2cv(const sensor_msgs::ImageConstPtr &img_msg)
{
cv_bridge::CvImageConstPtr ptr;
sensor_msgs::Image img_tmp;
img_tmp.header = img_msg->header;
img_tmp.height = img_msg->height;
img_tmp.width = img_msg->width;
img_tmp.is_bigendian = img_msg->is_bigendian;
img_tmp.step = img_msg->step;
img_tmp.data = img_msg->data;
img_tmp.encoding =img_msg->encoding;
ptr = cv_bridge::toCvCopy(img_tmp, sensor_msgs::image_encodings::BGR8);
cv::Mat img = ptr->image.clone();
return img;
}
//With reference of VINS rosNodeTest.cpp
void display()
{
while(1)
{
cv::Mat image0, image1;
// double t1,t2;
m_buf.lock();
if(!img0_buf.empty() && !img1_buf.empty())
{
ROS_INFO("Two cameras work");
image0=msg2cv(img0_buf.front());
// ROS_INFO("img0 %.9lf", img0_buf.front()->header.stamp.toSec());
// t1=img0_buf.front()->header.stamp.toSec();
img0_buf.pop();
imshow("camera1", image0);
image1=msg2cv(img1_buf.front());
// ROS_INFO("img1 %.9lf", img1_buf.front()->header.stamp.toSec());
// t2=img1_buf.front()->header.stamp.toSec();
img1_buf.pop();
cv::imshow("camera2", image1);
cv::waitKey(1);
}
m_buf.unlock();
// //display with cv
// if(!image0.empty())
// {
// imshow("camera1", image0);
// // cv::waitKey(1);
// }
// // else
// // { std::cout<<"image0 is empty!"<<std::endl;}
// if(!image1.empty())
// {
// imshow("camera2", image1);
// // cv::waitKey(1);
// }
// else
// {std::cout<<"image1 is empty!"<<std::endl;}
// cv::waitKey();
//std::chrono::milliseconds dura(2);
//std::this_thread::sleep_for(dura);
}
}
int main(int argc, char** argv)
{
//Initialize a ros node
ros::init(argc,argv,"demo");
ros::NodeHandle n;
ros::console::set_logger_level(ROSCONSOLE_DEFAULT_NAME, ros::console::levels::Info);
//Subscribe the binocular camera raw data
ros::Subscriber sub_img0=n.subscribe("/camera1/usb_cam1/image_raw", 2000, img0_callback);
ros::Subscriber sub_img1=n.subscribe("/camera2/usb_cam2/image_raw", 2000, img1_callback);
ROS_INFO("Wait for camera data.");
if(flag != 0) //for rviz
{
pubImg0 = n.advertise<sensor_msgs::Image>("/Img0", 100);
pubImg1 = n.advertise<sensor_msgs::Image>("/Img1", 100);
std::cout<<"for rviz"<<std::endl;
}
else //for cv
{
//Synchronization and display
std::cout<<"for cv"<<std::endl;
std::thread sync_thread{display};
sync_thread.detach();
//display();
}
ros::spin();
return 1;
}
The result now is that there is a camera slow. Is there some one to say something about the problem? I am not sure that the problem is from the OpenCv display or multi-thread coding. Thank you!
I started working on a project that turns 3d point clouds from a file into grid_map. After successfully having set all my project in CMake I was trying to prepare a small example. I am already able to publish a grid_map from this tutorial as it is possible to see from the print screen below:
Also from this source it seems to be possible to feed a grid_map with some point clouds that I have in a file on my Desktop.
However I am finding this process a little bit difficult mostly because I am still not confident with grid_map as I started working with it recently.
Below I am putting the code I am using to try to feed grid_map with a point cloud file I have on my Desktop:
#include <ros/ros.h>
#include <grid_map_ros/grid_map_ros.hpp>
#include <Eigen/Eigen>
#include <grid_map_msgs/GridMap.h>
#include <string>
#include <cstring>
#include <cmath>
#include <iostream>
#include <sensor_msgs/PointCloud.h>
#include <sensor_msgs/PointCloud2.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
using namespace grid_map;
class Point_CLoud_Reader
{
public:
Point_CLoud_Reader();
void pointCloudCallback(const sensor_msgs::PointCloudConstPtr& msgIn);
void readPCloud();
void writeToGridMap();
pcl::PointCloud<pcl::PointXYZ> cloud;
private:
ros::NodeHandle _node;
ros::Publisher pCloudPub;
ros::Subscriber pCloudSub;
std::string _pointTopic;
};
Point_CLoud_Reader::Point_CLoud_Reader()
{
_node.param<std::string>("pointcloud_topic", _pointTopic, "detections");
ROS_INFO("%s subscribing to topic %s ", ros::this_node::getName().c_str(), _pointTopic.c_str());
pCloudPub = _node.advertise<sensor_msgs::PointCloud>("/point_cloud", 100, &Point_CLoud_Reader::pointCloudCallback, this);
}
void Point_CLoud_Reader::pointCloudCallback(const sensor_msgs::PointCloudConstPtr &msgIn)
{
sensor_msgs::PointCloud msgPointCloud = *msgIn;
//msgPointCloud.points = cloud; // <-- Error Here
pCloudPub.publish(msgPointCloud);
}
void Point_CLoud_Reader::readPCloud()
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
if(pcl::io::loadPCDFile<pcl::PointXYZ> ("/home/to/Desktop/wigglesbank_20cm.pcd", *cloud) == -1) // load point cloud file
{
PCL_ERROR("Could not read the file /home/to/Desktop/wigglesbank_20cm.pcd \n");
return;
}
std::cout<<"Loaded"<<cloud->width * cloud->height
<<"data points from /home/to/Desktop/wigglesbank_20cm.pcd with the following fields: "
<<std::endl;
for(size_t i = 0; i < cloud->points.size(); ++i)
std::cout << " " << cloud->points[i].x
<< " " << cloud->points[i].y
<< " " << cloud->points[i].z << std::endl;
}
int main(int argc, char** argv)
{
// initialize node and publisher
ros::init(argc, argv, "grid_map_test");
ros::NodeHandle nh;
ros::Publisher pub = nh.advertise<grid_map_msgs::GridMap>("grid_map", 1, true);
ros::Publisher pCloudPub= nh.advertise<sensor_msgs::PointCloud>("point_cloud", 1, true);
pcl::PointCloud<pcl::PointXYZ> cloud;
// create grid map
GridMap map({"elevation"});
map.setFrameId("map");
map.setGeometry(Length(1.2, 2.0), 0.03);
ROS_INFO("Created map with size %f x %f m (%i x %i cells).",
map.getLength().x(), map.getLength().y(),
map.getSize()(0), map.getSize()(1));
// work with grid-map in a loop
ros::Rate rate(30.0);
while (nh.ok()) {
// add data to grid-map and point cloud from file just read
ros::Time time = ros::Time::now();
for(GridMapIterator it(map); !it.isPastEnd(); ++it)
for(int i = 0; i < cloud.points.size(); i++)
{
Point_CLoud_Reader readCloud;
readCloud.readPCloud(); // <-- Not reading point clouds
Position position;
map.getPosition(*it, position);
map.at("elevation", *it) = -0.04 + 0.2 * std::tan(3.0 * time.toSec() + 5.0 * position.y()) * position.x();
}
// publish a grid map and point cloud from file just read
map.setTimestamp(time.toNSec());
grid_map_msgs::GridMap msg;
sensor_msgs::PointCloud cloud;
GridMapRosConverter::toMessage(map, msg);
//GridMapRosConverter::toPointCloud(msg,cloud); <-- Error Here
pub.publish(msg);
pCloudPub.publish(cloud);
ROS_INFO_THROTTLE(1.0, "Grid map (timestamp %f) published.", msg.info.header.stamp.toSec());
// wait for next cycle
rate.sleep();
}
return 0;
}
Thanks for pointing in the right direction and shedding light on this issue
I already used SDL2 before, and now I try to use it with openGL 2.1.
But when I try to create a renderer, I get "Invalid renderer".
For creating a renderer I already use the same line before for simple SDL2 project, but with openGL it appears to not work properly.
Does someone have an idea why ?
I tried to change the flags of CreateRenderer, and I have this error for all of them except "SDL_RENDERER_SOFTWARE", but with him I can't grab input properly, and when the mouse cursor goes out the Window I have this error : "Invalid window".
Here is my code :
#include <SDL2/SDL.h>
#include <GL/glut.h>
#include <iostream>
const int WIDTH = 500, HEIGHT = 500;
using namespace std;
SDL_Window* pWindow;
SDL_Renderer* pRenderer;
SDL_Event event;
void initOGL()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(70,(double)WIDTH/HEIGHT,1,1000);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
}
void initSDL()
{
if (SDL_Init(SDL_INIT_VIDEO) != 0)
{
cout << "Video init failed" << endl;
exit(EXIT_FAILURE);
}
cout << "Video initialized" << endl;
// Window creation
pWindow = SDL_CreateWindow("Test OGL w/ SDL2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
if (!pWindow)
{
cout << "Window creation failed" << endl;
exit(EXIT_FAILURE);
}
cout << "Window created" << endl;
// Renderer creation
pRenderer = SDL_CreateRenderer(pWindow, -1, SDL_RENDERER_ACCELERATED);
if (!pRenderer)
{
cout << "Renderer creation failed" << endl;
}
cout << "Renderer created" << endl;
// OGL version
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
// OGL context
SDL_GLContext contexteOGL = SDL_GL_CreateContext(pWindow);
if (!contexteOGL)
{
cout << "Echec création du contexte" << endl;
}
cout << "Contexte créé" << endl;
}
int main(int argc, char const *argv[])
{
initSDL();
initOGL();
cout << "SDL_ERROR : " << SDL_GetError() << endl;
return 0;
}
I could be a "built-in supported driver" problem if you compiled SDL from source in Linux for example.
Try to use "flags = 0" in SDL_CreateRenderer(pWindow, -1, 0);
Then test the actual selected renderer (this is in C):
SDL_RendererInfo ri;
SDL_GetRendererInfo(pRenderer, &ri);
int n = SDL_GetNumRenderDrivers();
printf("Rendering drivers (%i):", n);
for(int i = 0; i < n; i++) {
SDL_RendererInfo info;
SDL_GetRenderDriverInfo(i, &info);
printf(" '%s'", info.name);
}
printf(", active = '%s'\n", ri.name);
Full source code is here
Okay, so I am trying to load a window and display a couple of images on it using a function. The window loads and my errors don't display for a failure to load the image, however the window just stays white. Any ideas why that might be? This is my code below.
#include "stdafx.h"
#include "SDL.h"
#include <iostream>
#include <string>
using namespace std;
const int Window_Width = 640;
const int Window_Height = 480;
SDL_Window *window = NULL;
SDL_Renderer *render = NULL;
SDL_Texture* loadImage(string imagename) //function that loads the image, useful for handling multiple image imports
{
SDL_Surface* loadedImage = NULL;
SDL_Texture* texture = NULL;
loadedImage = SDL_LoadBMP(imagename.c_str()); //loads the image with the passed file name
if (loadedImage == NULL) //checks for any errors loading the image
{
cout<<"The image failed to load.."<<endl;
}
texture = SDL_CreateTextureFromSurface(render, loadedImage);
SDL_FreeSurface(loadedImage);
return texture;
}
int main(int argc, char** argv)
{
if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
cout << SDL_GetError() << endl;
return 1;
}
window = SDL_CreateWindow("Frogger", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, Window_Width, Window_Height, SDL_WINDOW_SHOWN);
//creates a window in the centre of the screen, it uses const int's to define the size of the window
if (window == NULL)
{
cout << SDL_GetError()<<endl;
return 1;
}
render = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
//this renders the window
if (render == NULL)
{
cout << SDL_GetError()<<endl;
return 1;
}
//loading the images using the function
SDL_Texture* background = NULL;
SDL_Texture* frog = NULL;
background = loadImage("background.bmp");
frog = loadImage("frogger.bmp");
SDL_Delay(2000);
SDL_RenderClear(render);
SDL_RenderPresent(render);
SDL_UpdateWindowSurface(window);
//freeing the memory back up
SDL_DestroyRenderer(render);
SDL_DestroyWindow(window);
SDL_DestroyTexture(background);
SDL_DestroyTexture(frog);
SDL_Quit();
return 0;
}
You aren't rendering anything, you just load some textures and end the program.
I'm fighting with this problem from a long time.
I can't get OpenCV to work, and I have follow a lot of tutorials about it and how to use in Qt, so I get tired and I want to avoid the use of OpenCV for this.
Now, my requirement or question... I need to show a webcam feed (real time video, without audio) in a Qt GUI application with only one button: "Take Snapshot" which, obviusly, take a picture from the current feed and store it.
That's all.
Is there anyway to get this done without using OpenCV ?
System specification:
Qt 4.8
Windows XP 32 bits
USB 2.0.1.3M UVC WebCam (the one I'm using now, it should support other models too)
Hope anybody can help me with this because I'm getting crazy.
Thanks in advance!
Ok, I finally did it, so I will post here my solution so we have something clear about this.
I used a library called 'ESCAPI': http://sol.gfxile.net/escapi/index.html
This provide a extremely easy way to capture frames from the device. With this raw data, I just create a QImage which later show in a QLabel.
I created a simple object to handle this.
#include <QDebug>
#include "camera.h"
Camera::Camera(int width, int height, QObject *parent) :
QObject(parent),
width_(width),
height_(height)
{
capture_.mWidth = width;
capture_.mHeight = height;
capture_.mTargetBuf = new int[width * height];
int devices = setupESCAPI();
if (devices == 0)
{
qDebug() << "[Camera] ESCAPI initialization failure or no devices found";
}
}
Camera::~Camera()
{
deinitCapture(0);
}
int Camera::initialize()
{
if (initCapture(0, &capture_) == 0)
{
qDebug() << "[Camera] Capture failed - device may already be in use";
return -2;
}
return 0;
}
void Camera::deinitialize()
{
deinitCapture(0);
}
int Camera::capture()
{
doCapture(0);
while(isCaptureDone(0) == 0);
image_ = QImage(width_, height_, QImage::Format_ARGB32);
for(int y(0); y < height_; ++y)
{
for(int x(0); x < width_; ++x)
{
int index(y * width_ + x);
image_.setPixel(x, y, capture_.mTargetBuf[index]);
}
}
return 1;
}
And the header file:
#ifndef CAMERA_H
#define CAMERA_H
#include <QObject>
#include <QImage>
#include "escapi.h"
class Camera : public QObject
{
Q_OBJECT
public:
explicit Camera(int width, int height, QObject *parent = 0);
~Camera();
int initialize();
void deinitialize();
int capture();
const QImage& getImage() const { return image_; }
const int* getImageRaw() const { return capture_.mTargetBuf; }
private:
int width_;
int height_;
struct SimpleCapParams capture_;
QImage image_;
};
#endif // CAMERA_H
It's so simple, but just for example purposes.
The use should be something like:
Camera cam(320, 240);
cam.initialize();
cam.capture();
QImage img(cam.getImage());
ui->label->setPixmap(QPixmap::fromImage(img));
Of course, you can use a QTimer and update the frame in QLabel and you will have video there...
Hope it help! and thanks Nicholas for your help!