I was trying to load image using opeimageio which I installed using vcpkg. But I get an error saying F:\vcpkg\installed\x64-windows\include\OpenImageIO\fmt\format-inl.h(1371,8): error C2061: syntax error: identifier 'HANDLE'. My code is this
#include <OpenImageIO/imageio.h>
#include <string_view>
#include <tuple>
#include <vector>
std::tuple<int, int, int> loadImageFromFile(std::string_view filePath,
std::vector<unsigned char> &data) { auto input = OIIO::ImageInput::open(filePath.data());
auto &specs = input->spec();
int width = specs.width;
int height = specs.height;
int channels = specs.nchannels;
data = std::vector<unsigned char>(width * height * channels);
input->read_image(OIIO::TypeDesc::UINT8, &data[0]);
input->close();
return {width, height, channels};
}
Thanks!
Related
I am trying to use the sinusoidal pattern tool in C++ with Visual Studio. I have placed the code that I am testing this with below. In visual studio everything looks fine bar the red squiggle under params in the following line:
Ptr<structured_light::SinusoidalPattern> sinus = structured_light::SinusoidalPattern::create(params);
When I try to build I get the following error message:
Severity Code Description Project File Line Suppression State Error (active)
no suitable user-defined conversion from
"cv::structured_light::SinusoidalPattern::Params" to
"cv::Ptr<cv::structured_light::SinusoidalPattern::Params>" exists Structured_Light_Test
c:\Users\ianco\Desktop\CPlusPlus_Programming\Structured_Light_Test\Structured_Light_Test\Main.cpp 70
I would be very grateful if anyone could offer some advice on how I could get round this issue or suggest another method.
CODE:
#include <opencv2/highgui.hpp>
#include <vector>
#include <iostream>
#include <fstream>
#include <opencv2/core.hpp>
#include <opencv2/core/utility.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/calib3d.hpp>
#include <opencv2/structured_light.hpp>
#include <opencv2/phase_unwrapping.hpp>
using namespace cv;
using namespace std;
int main(int argc, char **argv)
{
structured_light::SinusoidalPattern::Params params;
params.width = 1080;
params.height = 700;
params.nbrOfPeriods = 5;
params.setMarkers = true;
params.horizontal = false;
params.methodId = 2;
params.shiftValue = static_cast<float>(2 * CV_PI / 3);
params.nbrOfPixelsBetweenMarkers = 70;
String outputPatternPath = "C:/Users/ianco/Desktop/CPlusPlus_Programming";
String outputWrappedPhasePath = "C:/Users/ianco/Desktop/CPlusPlus_Programming";
String outputUnwrappedPhasePath = "C:/Users/ianco/Desktop/CPlusPlus_Programming";
Ptr<structured_light::SinusoidalPattern> sinus = structured_light::SinusoidalPattern::create(params);
// Storage for patterns
vector<Mat> patterns;
//Generate sinusoidal patterns
sinus->generate(patterns);
cv::Mat blue, green, red;
std::vector<cv::Mat> images(3);
// OpenCV works natively with BGR ordering
images.at(0) = patterns[0];
images.at(1) = patterns[1];
images.at(2) = patterns[2];
cv::Mat color;
cv::merge(images, color);
namedWindow("pattern", WINDOW_NORMAL);
setWindowProperty("pattern", WND_PROP_FULLSCREEN, WINDOW_FULLSCREEN);
imshow("pattern", color);
waitKey(3000);
}
The documentation tells you that params should also be a Ptr but you passed the object...
try using makePtr
Change this line:
structured_light::SinusoidalPattern::Params params;
with this:
Ptr<cv::structured_light::SinusoidalPattern::Params> params = makePtr< SinusoidalPattern::Params >();
you will have to change . to -> for each use of params like params.width = 1080; would be params->width = 1080;, since it will be a pointer now.
The rest of the code should be ok.
I'm trying to make a simple ANN network with opencv in QT and develop it more later ,
I tried with simple data and i get an error says : OpenCV Error : asserion failed ((unsigned)(i1 *datatype<_tp>::channels)) < unsigned(size.p[1]* channels())) in cv::mat::at
here's the code I wrote
#include <iostream>
#include <opencv2/ml.hpp>
#include <opencv/cv.h>
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "nnet.h"
using namespace std;
using namespace cv;
int main()
{
string filename="data.csv";
Ptr<cv::ml::TrainData> tdata = cv::ml::TrainData::loadFromCSV(filename,0,-1,-1);
Mat trainData = tdata->getTrainSamples();
Mat trainLabels = tdata->getTrainResponses();
int numClasses = 3;
Mat hot(trainLabels.rows, numClasses, CV_32F, 0.0f);
for (int i=0; i<trainLabels.rows; i++) {
int id = (int)trainLabels.at<float>(i);
hot.at<float>(i, id) = 1.0f;
}
int input_neurons = 5;
int hidden_neurons = 5;
int output_neurons = 3;
Mat layerSizes = Mat(3, 1, CV_32SC1);
layerSizes.row(0) = Scalar(input_neurons);
layerSizes.row(1) = Scalar(hidden_neurons);
layerSizes.row(2) = Scalar(output_neurons);
Ptr<cv::ml::ANN_MLP> myNetwork = cv::ml::ANN_MLP::create();
myNetwork->setLayerSizes(layerSizes);
myNetwork->setTrainMethod(ml::ANN_MLP::SIGMOID_SYM);
myNetwork->setTermCriteria(TermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 1000, 0.00001f));
myNetwork->setTrainMethod(ml::ANN_MLP::BACKPROP,0.1f,0.1f);
myNetwork->setActivationFunction(ml::ANN_MLP::SIGMOID_SYM, 1, 1);
myNetwork->train(trainData, 0, hot);
string testfilename="test-data.csv";
Ptr<cv::ml::TrainData> testdata = cv::ml::TrainData::loadFromCSV(testfilename, 0,0,-1);
Mat testData = testdata->getTrainSamples();
Mat testLabels = testdata->getTrainResponses();
Mat testResults;
myNetwork->predict(testData, testResults);
float accuracy = float(countNonZero(testResults == testLabels)) / testLabels.rows;
printf("%f",accuracy);
return 0;
}
and for the data set i have
data.csv contains
1,2,3,7,2
7,1,7,7,5
9,7,5,3,2
12,21,32,71,8
and data-test.csv contains :
1,2,1,1,2,
9,1,2,12,5,
11,28,14,50,8,
3,1,2,12,5,
11,28,24,20,8,
thank you in advance for your help.
i found the solution to my problem , in the csv file i've i have 3 classes and the response values should be between [0..2] and i gave random numbers 5 and 8 so changing them solved this problem
Used stride by me generates exception. I don't know what stride is correct. The input image is 32 bit JPG. Please tell me what values(I tried many things but they where generating exceptions or corrupted JPG) i should put into:
array<System::Byte>^ pixels = gcnew array<System::Byte>(WHAT VALUE);
bitmapSource->CopyPixels(pixels, WHAT VALUE, 0);
// Jpg.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#using <mscorlib.dll> //requires CLI
using namespace System;
using namespace System::IO;
using namespace System::Windows::Media::Imaging;
using namespace System::Windows::Media;
using namespace System::Windows::Controls;
using namespace std;
[System::STAThread]
int _tmain(int argc, _TCHAR* argv[])
{
// Open a Stream and decode a JPEG image
Stream^ imageStreamSource = gcnew FileStream("C:/heart2.jpg",
FileMode::Open, FileAccess::Read, FileShare::Read);
JpegBitmapDecoder^ decoder = gcnew JpegBitmapDecoder(
imageStreamSource, BitmapCreateOptions::PreservePixelFormat,
BitmapCacheOption::Default);
BitmapSource^ bitmapSource = decoder->Frames[0];//< --mamy bitmape
// Draw the Image
Image^ myImage = gcnew Image();
myImage->Source = bitmapSource;
myImage->Stretch = Stretch::None;
myImage->Margin = System::Windows::Thickness(20);
int width = bitmapSource->PixelWidth;
int height = bitmapSource->PixelHeight;
int stride = (width * bitmapSource->Format.BitsPerPixel + 31) / 32;
array<System::Byte>^ pixels
= gcnew array<System::Byte>(height * width * stride);
bitmapSource->CopyPixels(pixels, stride, 0);
int x;
cin >> x;
return 0;
}
Google
http://msdn.microsoft.com/en-us/library/system.drawing.imaging.bitmapdata.stride.aspx
The stride is the width of a single row of pixels (a scan line), rounded up to a four-byte boundary.
So the correct value depends on how many bits per pixel you have in your image.
As in the subject how to include JpegBitmapDecoder^ in C++/CLI project. I have tried inlude namespace but I get:
Error 1 error C3083: 'Windows': the symbol to the left of a '::' must be a type C:\Users\Duke\Documents\Visual Studio 2010\Projects\Jpg\Jpg\Jpg.cpp 8 1 Jpg
Error 2 error C3083: 'Media': the symbol to the left of a '::' must be a type C:\Users\Duke\Documents\Visual Studio 2010\Projects\Jpg\Jpg\Jpg.cpp 8 1 Jpg
Error 3 error C2039: 'Imaging' : is not a member of 'System' C:\Users\Duke\Documents\Visual Studio 2010\Projects\Jpg\Jpg\Jpg.cpp 8 1 Jpg
Error 4 error C2871: 'Imaging' : a namespace with this name does not exist C:\Users\Duke\Documents\Visual Studio 2010\Projects\Jpg\Jpg\Jpg.cpp 8 1 Jpg
Jpg
// Jpg.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#using <mscorlib.dll> //requires CLI
using namespace System;
using namespace System::IO;
using namespace System::Windows::Media::Imaging;
int _tmain(int argc, _TCHAR* argv[])
{
// Open a Stream and decode a JPEG image
Stream^ imageStreamSource = gcnew FileStream("C:\Users\Duke\Desktop\heart.jpg", FileMode::Open, FileAccess::Read, FileShare::Read);
JpegBitmapDecoder^ decoder = gcnew JpegBitmapDecoder(imageStreamSource, BitmapCreateOptions::PreservePixelFormat, BitmapCacheOption::Default);//i want that decoder
BitmapSource^ bitmapSource = decoder->Frames[0];//< --mamy bitmape
// Draw the Image
Image^ myImage = gcnew Image();
myImage->Source = bitmapSource;
myImage->Stretch = Stretch::None;
myImage->Margin = System::Windows::Thickness(20);
//
int width = 128;
int height = width;
int stride = width / 8;
array<System::Byte>^ pixels = gcnew array<System::Byte>(height * stride);
// Define the image palette
BitmapPalette^ myPalette = BitmapPalettes::Halftone256;
// Creates a new empty image with the pre-defined palette.
BitmapSource^ image = BitmapSource::Create(
width, height,
96, 96,
PixelFormats::Indexed1,
myPalette,
pixels,
stride);
System::IO::FileStream^ stream = gcnew System::IO::FileStream("new.jpg", FileMode::Create);
JpegBitmapEncoder^ encoder = gcnew JpegBitmapEncoder();
TextBlock^ myTextBlock = gcnew System::Windows::Controls::TextBlock();
myTextBlock->Text = "Codec Author is: " + encoder->CodecInfo->Author->ToString();
encoder->FlipHorizontal = true;
encoder->FlipVertical = false;
encoder->QualityLevel = 30;
encoder->Rotation = Rotation::Rotate90;
encoder->Frames->Add(BitmapFrame::Create(image));
encoder->Save(stream);
return 0;
}
Use this instead:
using namespace System::Windows::Media::Imaging;
Clearly, the line above that should have hinted that in C++/CLI, you use :: rather than ..
So I want to join all interrelated poligons in a multi_polygon. How to do such thing?
We have such image (of one green multi_polygon) which we want to optimize (we can see yellow doted lines - result of simplification that apparently was performed on each poligon of multi_polygon not on multi_polygon in general):
And here is compilable code to generate such image:
#include <iostream>
#include <fstream>
#include <boost/assign.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/geometry/geometry.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/multi/geometries/multi_polygon.hpp>
#include <boost/geometry/extensions/io/svg/svg_mapper.hpp>
template <typename Geometry1, typename Geometry2>
void create_svg(std::string const& filename, Geometry1 const& a, Geometry2 const& b)
{
typedef typename boost::geometry::point_type<Geometry1>::type point_type;
std::ofstream svg(filename.c_str());
boost::geometry::svg_mapper<point_type> mapper(svg, 400, 400);
mapper.add(a);
mapper.add(b);
mapper.map(a, "fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:2");
mapper.map(b, "opacity:0.8;fill:none;stroke:rgb(255,128,0);stroke-width:4;stroke-dasharray:1,7;stroke-linecap:round");
}
boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > make_point(int x, int y)
{
boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > return_item;
boost::geometry::model::d2::point_xy<double> p1(x, y);
boost::geometry::model::d2::point_xy<double> p2(x-1, y);
boost::geometry::model::d2::point_xy<double> p3(x-1, y-1);
boost::geometry::model::d2::point_xy<double> p4(x, y-1);
boost::geometry::append( return_item, p1);
boost::geometry::append( return_item, p2);
boost::geometry::append( return_item, p3);
boost::geometry::append( return_item, p4);
return return_item;
}
int main()
{
// create a container for joined points structure
boost::geometry::model::multi_polygon< boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > > output, simpl;
// join points one by one (because one day we would have many=))
output.push_back(make_point(1,1));
boost::geometry::correct(output);
output.push_back(make_point(2,1));
boost::geometry::correct(output);
output.push_back(make_point(3,1));
boost::geometry::correct(output);
output.push_back(make_point(4,1));
boost::geometry::correct(output);
output.push_back(make_point(5,1));
boost::geometry::correct(output);
output.push_back(make_point(2,2));
boost::geometry::correct(output);
output.push_back(make_point(3,2));
boost::geometry::correct(output);
output.push_back(make_point(5,2));
boost::geometry::correct(output);
output.push_back(make_point(5,5));
boost::geometry::correct(output);
// simplify joined structure
boost::geometry::simplify(output, simpl, 0.5);
// create an svg image
create_svg("make_envelope.svg", output, simpl );
}
requires at least boost 1.47.0 and 3 files from boost/geometry/extensions/io/svg/
what I need is simple: how to group interrelated poligons? In this case we shall get 2 poligons in our multy_poligon like shown here - red and green:
Update:
So I found this info on dissolve and created sample code that uses rings for cels creation:
#include <iostream>
#include <fstream>
#include <boost/assign.hpp>
//Boost
#include <boost/algorithm/string.hpp>
#include <boost/geometry/geometry.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/multi/geometries/multi_polygon.hpp>
#include <boost/geometry/geometries/adapted/boost_tuple.hpp>
BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)
#include <boost/foreach.hpp>
//Boost Geometry extensions (from trunk)
#include <boost/geometry/extensions/io/svg/svg_mapper.hpp>
template <typename Geometry1, typename Geometry2>
void create_svg(std::string const& filename, Geometry1 const& a, Geometry2 const& b)
{
typedef typename boost::geometry::point_type<Geometry1>::type point_type;
std::ofstream svg(filename.c_str());
boost::geometry::svg_mapper<point_type> mapper(svg, 400, 400);
mapper.add(a);
mapper.add(b);
mapper.map(a, "fill-rule:nonzero;fill-opacity:0.5;fill:rgb(153,204,0);stroke:rgb(153,204,0);stroke-width:2;");
mapper.map(b, "opacity:0.8;fill:none;stroke:rgb(255,128,0);stroke-width:4;stroke-dasharray:1,7;stroke-linecap:round");
}
void make_point(int x, int y, boost::geometry::model::ring<boost::geometry::model::d2::point_xy<double> > & ring)
{
using namespace boost::assign;
ring +=
boost::geometry::model::d2::point_xy<double>(x-1, y-1),
boost::geometry::model::d2::point_xy<double>(x, y-1),
boost::geometry::model::d2::point_xy<double>(x, y),
boost::geometry::model::d2::point_xy<double>(x-1, y),
boost::geometry::model::d2::point_xy<double>(x-1, y-1);
}
int main()
{
using namespace boost::assign;
boost::geometry::model::ring<boost::geometry::model::d2::point_xy<double> > ring0, ring1,ring;
boost::geometry::model::multi_polygon< boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > > outputw;
make_point(1, 1, ring) ;
make_point(2, 1, ring) ;
make_point(3, 1, ring) ;
make_point(4, 1, ring) ;
make_point(5, 1, ring) ;
make_point(2, 2, ring) ;
make_point(3, 2, ring) ;
make_point(5, 2, ring) ;
boost::geometry::model::ring<boost::geometry::model::d2::point_xy<double> > output;
boost::geometry::simplify(ring, output, 1);
// create an svg image
create_svg("make_envelope.svg", ring, output );
}
It returns such image of ring:
If we could use dissolve to turn it into poligon that would really solve some of my problems. But looks like currently we can not due to this compiler errors problem described here
What about using Qt. If you use a QPolygonF you can call unite which does exactly what you need. After unison you can extract the points and put them back into your boost container.
If qt is not an option take a look at the algorithms proposed here http://www.wykobi.com
You can use this function from boost library:
void union_(Geometry1 const & geometry1, Geometry2 const & geometry2, Collection & output_collection)
It takes two geometries and unites them if they have intersections or puts them into one collection (vector, deque, etc.) if not.