How to convert 4 dimensional matrix to NHWC format in OpenCV - c++

So I'm in the middle of implementing SIFT and the thing is that I don't know how to deal with channel in OpenCV. Here is what I've done so far.
#ifndef QUANTIZATION_DATABASE_DATA_READ_H
#define QUANTIZATION_DATABASE_DATA_READ_H
// C HEADERS
#include <stdlib.h>
#include <fcntl.h>
// C++ HEADERS
#include <iostream>
#include <string>
// OPENCV HEADERS
#include <opencv2/opencv.hpp>
namespace cv
{
class DataReader
{
public:
explicit DataReader(int _flags) : flags(_flags)
{
}
void read(std::string filename, const char *key, Mat &res)
{
try
{
FileStorage fs(filename, FileStorage::Mode::FORMAT_XML | FileStorage::Mode::READ);
fs[key] >> res;
fs.release();
}
catch (Exception e)
{
std::cerr << e.msg << std::endl;
}
}
private:
int flags;
};
}
The algorithm that I want to implement is as follow.
Read the 4 dimensional matrix(NHWC) from a xml file.
Store it in a matrix
Convert it into NHWC
The thing is that I don't have to do step 3 when I do some stuffs using Tensorflow. It just automatically knows the last dimension is channel. So, what should I do?

It seems like there is no way whatsoever to make 4 dimensional buffer to a batch of images. So I decided to change the format of the xml file and it worked like a charm.
Below is temporarily workaround for this problem.
#ifndef QUANTIZATION_DATABASE_DATA_READ_H
#define QUANTIZATION_DATABASE_DATA_READ_H
// C HEADERS
#include <stdlib.h>
#include <fcntl.h>
// C++ HEADERS
#include <iostream>
#include <string>
// OPENCV HEADERS
#include <opencv2/opencv.hpp>
namespace cv
{
class DataReader
{
public:
explicit DataReader(int _flags) : flags(_flags)
{
}
void read(std::string filename, Mat &res)
{
try
{
float length = 0;
FileStorage fs(filename, FileStorage::Mode::FORMAT_XML | FileStorage::Mode::READ);
fs["size"] >> length;
for (int i = 0; i < (int)length; ++i) {
std::string key("image");
std::string index = std::to_string(i);
Mat image;
key = key + index;
fs[key.c_str()] >> image;
std::cout << image.channels() << std::endl;
res.push_back(image);
}
fs.release();
}
catch (Exception e)
{
std::cerr << e.msg << std::endl;
}
}
private:
int flags;
};
}

Related

Why do I get error C2143 syntax error: missing ';' before '*'?

I get the following errors:
Severity Code Description Project File Line Suppression State
Error C2143 syntax error: missing ';' before '*' flashlight d:\flashlight\orbslam3\examples\monocular\flashlight.hpp 36
Severity Code Description Project File Line Suppression State
Error C4430 missing type specifier - int assumed. Note: C++ does not
support
default-int flashlight d:\flashlight\orbslam3\examples\monocular\flashlight.hpp 36
Severity Code Description Project File Line Suppression State
Error C2238 unexpected token(s) preceding
';' flashlight d:\flashlight\orbslam3\examples\monocular\flashlight.hpp 36
This is my header flashlight.hpp file:
#ifndef FLASHLIGHT_H
#define FLASHLIGHT_H
#include <cstdlib>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/thread/locks.hpp>
#include "orbslam3.hpp"
using boost::asio::ip::udp;
class Flashlight {
public:
Flashlight(boost::asio::io_service& io_service, short port) : io_service_(io_service), socket_(io_service, udp::endpoint(udp::v4(), port)) {
// start receiving udp data
socket_.async_receive_from(
boost::asio::buffer(data_recv_, max_length), sender_endpoint_, boost::bind(&Flashlight::handle_receive_from, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)
);
}
void start_loop();
void send_beacon();
void handle_send_to(const boost::system::error_code& error, size_t bytes_sent);
void handle_receive_from(const boost::system::error_code& error, size_t bytes_recvd);
private:
ORBSLAM3 *orbslam; // <= ERRORS APPEAR HERE (Line 36)
boost::asio::io_service& io_service_;
udp::socket socket_;
udp::endpoint sender_endpoint_;
enum { max_length = 1024 };
char data_recv_[max_length];
char data_sent_[max_length];
};
#endif
And this is my implementation file flashlight.cpp:
#include "flashlight.hpp"
using namespace std; // for atoi()
using boost::asio::ip::udp;
int main(int argc, char* argv[]) {
try {
const uint16_t udp_port = 19630;
// thread to run network services asynchronously
boost::thread_group tgroup;
// start udp network endpoint
boost::asio::io_service io_service;
// instantiate flashlight class
Flashlight flashlight(io_service, udp_port);
// run network entities in own thread
tgroup.create_thread(boost::bind(&boost::asio::io_service::run, &io_service));
cout << "Server running on UDP port " << udp_port << endl;
// start main loop
flashlight.start_loop();
// shutdown network threads
tgroup.join_all();
} catch(exception& e) {
cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
void Flashlight::start_loop() {
string sensor_type = "stereo";
string vocab_path = "D:\\Flashlight\\ORBSLAM3\\Examples\\Monocular\\Release\\ORBVoc.bin";
string settings_path = "D:\\Flashlight\\ORBSLAM3\\Examples\\Monocular\\Release\\stereo_2_8_mm_640_480.yaml";
//const string settings_path = "../"+sensor_type+"_"+lens_type+"_mm_"+to_string(cam_width)+"_"+to_string(cam_height)+".yaml";
uint16_t cam_width = 640;
uint16_t cam_height = 480;
// orb slam system initialization
this->orbslam = new ORBSLAM3(sensor_type, vocab_path, settings_path, cam_width, cam_height);
// mainloop
char key;
while((key = std::cin.get()) != 27) {
this->orbslam->loop();
}
// shutdown orbslam threads
this->orbslam->shutdown();
// save camera trajectory
//orbslam->SaveTrajectoryTUM("CameraTrajectory.txt");
}
void Flashlight::send_beacon() {
while(true) {
boost::posix_time::seconds workTime(1);
// send_async(beacon)
std::cout << "Beacon signal sent ..." << std::endl;
boost::this_thread::sleep(workTime);
}
}
void Flashlight::handle_receive_from(const boost::system::error_code& error, size_t bytes_recv) {
if(!error && bytes_recv > 0) {
std::cout << "UDP received: "; for(int i=0; i<bytes_recv; i++) std::cout << (int)data_recv_[i] << ", "; std::cout << std::endl;
// start listening again
socket_.async_receive_from(
boost::asio::buffer(data_recv_, max_length), sender_endpoint_, boost::bind(&Flashlight::handle_receive_from, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)
);
}
}
void Flashlight::handle_send_to(const boost::system::error_code& error, size_t bytes_sent) {
socket_.async_send_to(
boost::asio::buffer(data_sent_, bytes_sent), sender_endpoint_, boost::bind(&Flashlight::handle_send_to, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)
);
}
I can't spot what I am missing. Some idea?
UPDATE: added orbslam3.hpp and orbslam3.cpp
#ifndef ORBSLAM3_H
#define ORBSLAM3_H
#include <algorithm>
#include <fstream>
#include <chrono>
#include <opencv2/core/core.hpp>
#include <cstdlib>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/thread/locks.hpp>
#include "flashlight.hpp"
// ==============================
// IMPORTANT: Don NOT move up the
// ========== following include !
#include <System.h>
class ORBSLAM3 {
public:
ORBSLAM3(string &sensor_type, string &vocab_path, string &settings_path, uint16_t cam_width, uint16_t cam_height);
int loop();
void pause();
void resume();
void reset();
void setMode(bool mapping); // false := localization only, true := localization+mapping
void saveMap();
void loadMap();
void shutdown();
private:
string sensor_type; // types = {"mono", "stereo", "rgbd")
string vocab_path; // path to the vocabulary (*.bin/*.txt)
string settings_path; // patch to the settings file (*.yaml)
uint16_t cam_width; // horizontal camera resolution
uint16_t cam_height; // vertical camera resolution
ORB_SLAM2::System *slam; // main orbslam system
cv::VideoCapture *cap1; // first camera capture devices
cv::VideoCapture *cap2; // second camera capture devices
cv::Mat img_left, img_right; // stereo images captured
cv::Mat tcw; // pose output information
};
#endif
And the implementation file orbslam3.cpp:
#include "orbslam3.hpp"
using namespace std;
ORBSLAM3::ORBSLAM3(string &sensor_type, string &vocab_path, string &settings_path, uint16_t cam_width, uint16_t cam_height) {
// assign arguments to local fields
this->sensor_type = sensor_type;
this->vocab_path = vocab_path;
this->settings_path = settings_path;
this->cam_width = cam_width;
this->cam_height = cam_height;
// initialize ORBSLAM system
if(sensor_type.compare("mono")==0) {
this->slam = new ORB_SLAM2::System(vocab_path, settings_path, ORB_SLAM2::System::MONOCULAR, true, true);
} else if(sensor_type.compare("stereo")==0) {
this->slam = new ORB_SLAM2::System(vocab_path, settings_path, ORB_SLAM2::System::STEREO, true, true);
} else if(sensor_type.compare("rgbd")==0) {
this->slam = new ORB_SLAM2::System(vocab_path, settings_path, ORB_SLAM2::System::RGBD, true, true);
} else {
std::cout << "ERROR: Unknown sensor type: " << sensor_type << std::endl;
}
// initialize cameras
cap1 = new cv::VideoCapture(0);
cap2 = new cv::VideoCapture(1);
// set camera resolutions
cap1->set(CV_CAP_PROP_FRAME_WIDTH, cam_width);
cap1->set(CV_CAP_PROP_FRAME_HEIGHT, cam_height);
cap2->set(CV_CAP_PROP_FRAME_WIDTH, cam_width);
cap2->set(CV_CAP_PROP_FRAME_HEIGHT, cam_height);
}
int ORBSLAM3::loop() {
// capture left and right images
cap1->read(img_right);
cap2->read(img_left);
// convert to b/w
//cv::cvtColor(imRight, imRight, CV_BGR2GRAY);
//cv::cvtColor(imLeft, imLeft, CV_BGR2GRAY);
// check image validity
if(img_left.empty()) {
cerr << endl << "Failed to capture left image." << endl;
return 1;
}
if(img_right.empty()) {
cerr << endl << "Failed to capture right image." << endl;
return 1;
}
// time
__int64 cnow = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
// pass the images to the SLAM system
tcw = slam->TrackStereo(img_left, img_right, cnow / 1000.0);
// visualize stereo images
cv::imshow("Left Image", img_left);
cv::imshow("Right Image", img_right);
}
void ORBSLAM3::pause() {
}
void ORBSLAM3::resume() {
}
void ORBSLAM3::reset() {
}
void ORBSLAM3::setMode(bool mapping) {
}
void ORBSLAM3::saveMap() {
}
void ORBSLAM3::loadMap() {
}
void ORBSLAM3::shutdown() {
slam->Shutdown();
cap1->release();
cap2->release();
}
Looks like you have a circular dependency.
Fix that and it should work.
flashlight.hpp
// Remove this line.
// #include "orbslam3.hpp"
// Add a forward declaration.
// Unless you need the full declaration you should not be including the header file
// Prefer to use forward declarations when you are just using a pointer.
class ORBSLAM3;
flashlight.cpp
#include "flashlight.hpp"
// Add this line.
// You will probably need the actual definition if you use it in the code.
#include "orbslam3.hpp"
orbslam3.hpp
// Does not even look you need this in the header file.
// Remove headers you don't need.
// #include "flashlight.hpp"

XDR serializing variable lenght array of string

I am serializing a packet over XDR but i do not understand how to provide vector of string. I have here a small fully working serialization / deserialization for a std::vector of uint64_t. Here my code:
Serializer:
#include <stdio.h>
#include <iostream>
#include <rpc/rpc.h>
#include <vector>
#define MAX_LENGTH_ 100
int main(void)
{
XDR xdr;
xdrstdio_create(&xdr, stdout, XDR_ENCODE);
std::vector<uint64_t> ids; // vector i want to send
ids.push_back(1);
ids.push_back(2);
ids.push_back(3);
// serializing the vector
uint64_t *_ids = &ids[0];
uint32_t size = ids.size();
xdr_array(&xdr,(char**)(&_ids), &size, MAX_LENGTH_,sizeof(uint64_t),(xdrproc_t)xdr_u_long);
return 1;
}
Deserializer:
#include <stdio.h>
#include <iostream>
#include <rpc/rpc.h>
#include <vector>
#define MAX_LENGTH_ 100
int main(void)
{
XDR xdrs;
xdrstdio_create(&xdrs, stdin, XDR_DECODE);
uint64_t *ids_ = new uint64_t[MAX_LENGTH_];
uint32_t size;
bool status = xdr_array(&xdrs,(char**)(&ids_), &size, MAX_LENGTH_,
sizeof(uint64_t), (xdrproc_t)xdr_u_long);
std::vector<uint64_t> ids(ids_,ids_+size);
for(std::vector<uint64_t>::iterator it = ids.begin(); it != ids.end(); ++it)
{
std::cout << *it <<std::endl;
}
return 1;
}
The following code works... running ./serializer | ./deserializer i obtain 1 2 3. Now I do not know how to handle having to serialize std::vector<std::string>. A single string works well using xdr_string.
http://linux.die.net/man/3/xdr_array
Any help would be very much appreciated!
EDIT:
I have tried the following:
Serializer:
#include <stdio.h>
#include <iostream>
#include <rpc/rpc.h>
#include <vector>
#include <algorithm>
#include <cstring>
#define MAX_VECTOR_LENGTH_ 100
#define MAX_STRING_LENGTH_ 50
char *convert(const std::string & s)
{
char *pc = new char[s.size()+1];
std::strcpy(pc, s.c_str());
return pc;
}
int main(void)
{
XDR xdr;
xdrstdio_create(&xdr, stdout, XDR_ENCODE);
std::vector<std::string> messages; // vector i want to send
messages.push_back("this is");
messages.push_back("my string");
messages.push_back("vector test");
// transform the vector to c style
std::vector<char*> messagesCStyle;
std::transform(messages.begin(), messages.end(), std::back_inserter(messagesCStyle), convert);
// serializing the vector
char **_messages = &messagesCStyle[0];
uint32_t size = messages.size();
xdr_array(&xdr,(char**)(&_messages), &size, MAX_VECTOR_LENGTH_ * MAX_STRING_LENGTH_,sizeof(char),(xdrproc_t)xdr_string);
return 1;
}
Deserializer:
#include <stdio.h>
#include <iostream>
#include <rpc/rpc.h>
#include <vector>
#define MAX_VECTOR_LENGTH_ 100
#define MAX_STRING_LENGTH_ 50
int main(void)
{
XDR xdrs;
xdrstdio_create(&xdrs, stdin, XDR_DECODE);
std::vector<char*> messagesCStyle_;
uint32_t size;
bool status = xdr_array(&xdrs,(char**)(&messagesCStyle_), &size, MAX_VECTOR_LENGTH_,
MAX_STRING_LENGTH_, (xdrproc_t)xdr_string);
for(std::vector<char*>::iterator it = messagesCStyle_.begin(); it != messagesCStyle_.end(); ++it)
{
std::cout << *it <<std::endl;
}
return 1;
}
I am pretty sure the code for the Serializer is not best but at least it seams to work. However the deserializer does not!! I think the problem is related to the fact that i do not know how much memory to allocate before calling the xdr_array. Any help?
I made it work:
Encoder:
#include <stdio.h>
#include <iostream>
#include <rpc/rpc.h>
#include <vector>
#include <algorithm>
#include <cstring>
#define MAX_VECTOR_LENGTH_ 100
#define MAX_STRING_LENGTH_ 50
char *convert(const std::string & s)
{
char *pc = new char[s.size()+1];
std::strcpy(pc, s.c_str());
return pc;
}
int main(void)
{
XDR xdr;
xdrstdio_create(&xdr, stdout, XDR_ENCODE);
std::vector<std::string> messages; // vector i want to send
messages.push_back("this is");
messages.push_back("my string");
messages.push_back("vector test");
messages.push_back("this is a relatively long string!!!");
// transform the vector to c style
std::vector<char*> messagesCStyle;
std::transform(messages.begin(), messages.end(),
std::back_inserter(messagesCStyle),
[](const std::string & s){
char *pc = new char[s.size()+1];
std::strcpy(pc, s.c_str());
return pc;
});
// serializing the vector
char **_messages = &messagesCStyle[0];
uint32_t size = messages.size();
xdr_array(&xdr,(char**)(&_messages), &size, MAX_VECTOR_LENGTH_ * MAX_STRING_LENGTH_,sizeof(char*),(xdrproc_t)xdr_string);
return 1;
}
Decoder:
#include <stdio.h>
#include <iostream>
#include <rpc/rpc.h>
#include <vector>
#define MAX_VECTOR_LENGTH_ 100
#define MAX_STRING_LENGTH_ 50
int main(void)
{
XDR xdrs;
uint32_t size;
char** buffer = NULL;
xdrstdio_create(&xdrs, stdin, XDR_DECODE);
bool status = xdr_array(&xdrs, (char**) &buffer, &size, MAX_VECTOR_LENGTH_,
sizeof(char*), (xdrproc_t)xdr_string);
std::cout << "status: " << status << std::endl;
std::cout << "size: " << size << std::endl;
std::vector<std::string> stringMessages_(buffer, buffer + size);
for(std::vector<std::string>::iterator it = stringMessages_.begin(); it != stringMessages_.end(); ++it)
{
std::cout << *it <<std::endl;
}
for (int i = 0; i < size; i++) {
free(buffer[i]);
}
free(buffer);
return 1;
}

Boost property tree Bad path for nothing

I am having trouble with this library... My code works fine, the parsers/creator works too, but an err appears, I don't know why:
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/thread.hpp>
#include <string>
#include <exception>
#include <set>
#include <iostream>
#include "journal.h"
unsigned short port = 2013;
unsigned short maxConnec = 250;
unsigned short fPort() {return port;}
unsigned short fMaxConnec() {return maxConnec;}
bool load(const std::string &file)
{
using boost::property_tree::ptree;
ptree objectXML;
std::cout << "bbb";
read_xml(file, objectXML);
std::cout << "aaa";
if (file.length() == 0) // By the way, no way to do that better ? "if file doesn't exist..."
{
return 0;
}
else
{
port = objectXML.get<unsigned short>("configuration.server.port");
maxConnec = objectXML.get<unsigned short>("configuration.server.maxConnections");
return 1;
}
}
bool save(const std::string &file)
{
try
{
using boost::property_tree::ptree;
ptree objectXML;
objetXML.put("configuration.server.port", port);
objetXML.put("configuration.server.maxConnections", maxConnec);
write_xml(file, objectXML, std::locale(), boost::property_tree::xml_writer_make_settings<ptree::key_type>(' ', 4));
return 1;
}
catch (std::exception e)
{
return 0;
}
}
void generate()
{
std::string file = "configuration.xml";
try{
if (!load(fichier))
{
save(file);
}
}
catch (std::exception &e)
{
load(file);
}
}
Get a bad path, I totally don't know why because when I try to read data I can and it gets the data in configuration.xml even if I change it...
The ptree_bad_path exception is raised from the throwing version of get and signals that "configuration.server.port" or "configuration.server.maxConnections" path to the XML element doesn't exist.
The error isn't related to the configuration.xml file path.
So you should check the element name or, for optional elements, use the default-value / optional-value version of get.

header include in main.cpp works, but throws error in class

I had asked this question here. But the problem seems to be something else so re-posting here..
I am including the header <zbar.h> from Zbar library in main.cpp and the sample code works perfectly fine.
#include <iostream>
#include <Magick++.h>
#include <zbar.h>
#include <highgui.h>
#include <cv.h>
using namespace std;
using namespace zbar;
using namespace cv;
int main (int argc, char **argv){
if(argc < 2) return(1);
// create a reader
ImageScanner scanner;
// configure the reader
scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);
// obtain image data
Magick::Image magick(argv[1]); // read an image file
int width = magick.columns(); // extract dimensions
int height = magick.rows();
Magick::Blob blob; // extract the raw data
magick.modifyImage();
magick.write(&blob, "GRAY", 8);
const void *raw = blob.data();
// wrap image data
Image image(width, height, "Y800", raw, width * height);
// scan the image for barcodes
int n = scanner.scan(image);
cv::Mat dispImage = imread(argv[1]);
// extract results
for(Image::SymbolIterator symbol = image.symbol_begin();
symbol != image.symbol_end();
++symbol) {
// do something useful with results
cout << "decoded " << symbol->get_type_name()
<< " symbol \"" << symbol->get_data() << '"' << endl;
}
}
// clean up
image.set_data(NULL, 0);
return(0);
}
But if I make a dummy class and include zbar.h in the header of this class, I get the following error :
the default argument for parameter 0 of ‘zbar::Exception::Exception(const void*)’ has not yet been parsed line 144, external location: /usr/local/include/zbar/Exception.h C/C++ Problem
#ifndef DUMMY_H
#define DUMMY_H
#include <zbar.h>
class dummy{
public:
dummy();
};
#endif // DUMMY_H
I even tried with
extern "C"{
#include <zbar.h>
}
but it throws 100s of template with C linkage error.
According to this documentation, the constructor is declared as
Exception(const void * = NULL);
The error suggests that NULL hasn't been declared; meaning that nothing has included <cstddef>. You should be able to fix it by including that yourself, before the evil header.

Serializing to a binary archive using boost. Input Stream Error

I try to serialize to a binary archive then load this archive using the code show below. The issue I have is that when loading the file, I get an "input stream error".
#include "project.h"
// Std
#include <fstream>
// Boost
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/algorithm/string.hpp>
// Qt
#include <QtGui/QMessageBox>
#include <QFileInfo>
#include <QDir>
BOOST_CLASS_VERSION(Tools::CommentModel, 1)
using namespace std;
namespace Sawe {
template<class Archive>
void runSerialization(Archive& ar, Project*& project, QString path)
{
const unsigned magicConst=65553;
unsigned magic = magicConst;
ar & BOOST_SERIALIZATION_NVP(magic);
if (magic != magicConst)
throw std::ios_base::failure("Wrong project type");
ar & BOOST_SERIALIZATION_NVP(project);
}
bool Project::
save()
{
if (project_filename_.empty()) {
return saveAs();
}
try
{
std::ofstream ofs(project_filename_.c_str());
assert(ofs.good());
boost::archive::binary_oarchive xml(ofs);
Project* p = this;
runSerialization(xml, p, project_filename_.c_str());
p->is_modified_ = false;
}
catch (const std::exception& x)
{
QString msg = "Error: " + QString::fromStdString(vartype(x)) +
"\nDetails: " + QString::fromLocal8Bit(x.what());
QMessageBox::warning( 0, "Can't save file", msg );
TaskInfo("======================\nCan't save file\n%s\n======================", msg.toStdString().c_str());
}
return true;
}
#endif
pProject Project::
openProject(std::string project_file)
{
std::ifstream ifs(project_file.c_str());
boost::archive::binary_iarchive xml(ifs);
Project* new_project = 0;
runSerialization(xml, new_project, project_file.c_str());
new_project->project_filename_ = project_file;
new_project->updateWindowTitle();
new_project->is_modified_ = false;
pProject project( new_project );
return project;
}
}
Any idea ?
Thanks in advance for your help!
Cheers
I had the same problem, when i added the binary flag to the fstream ctors everything worked.