Reputation: 489
I want to load a large number of images in my program, to later stitch them together. I am using commandline to mention image address. It works if I know in advance the number of images I will have in input but it doesn't works for variable number of input images:
if (argc < 3)
{
cerr<<"Usage:" << argv[0] << "SOURCE DESTINATION" << endl;
return 1;
}
for (int i = 0;i <argc;i++)
{
Mat img[i] = imread(argv[i+1], 0);
imshow("image", img[i]);
}
Is there any other method to get inputs in this case. I need to work on 20 to 25 images. Can I use some file, storing address and read that. I think it is possible, but how does it work?
Edit:
After some modifications, my program now look like this:
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc_c.h"
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/calib3d/calib3d.hpp"
#include <math.h>
#include <cmath>
#define PI 3.14159
#define max_img 25
using namespace cv;
using namespace std;
//main function
int main(int argc, char** argv)
{const int MAX_NUM_OF_IMG = 1024;
cv::Mat img[MAX_NUM_OF_IMG];
for(int i=1;i<argc;i++)
{
std::cout << i << ": " << argv[i] << std::endl;
img[i-1] = imread(argv[i],0);
std::cout << "Finished reading images1" << std::endl;
imshow("image",img[i]);
//start stitching operations
}std::cout << "Finished reading images2" << std::endl;
cv::waitKey();
return 0;
}
I gave the following in the commandline:
./img_many camera3/imageb-032.jpgcamera3/imageb-033.jpgcamera3/imageb-034.jpgcamera3/imageb-035.jpgcamera3/imageb-036.jpgcamera3/imageb-037.jpgcamera3/imageb-038.jpgcamera3/imageb-039.jpg
The output I get is
1: camera3/imageb-032.jpgcamera3/imageb-033.jpgcamera3/imageb-034.jpgcamera3/imageb-035.jpgcamera3/imageb-036.jpgcamera3/imageb-037.jpgcamera3/imageb-038.jpgcamera3/imageb-039.jpg
Finished reading images1
OpenCV Error: Bad flag (parameter or structure field) (Unrecognized or unsupported array type) in cvGetMat, file /build/buildd/opencv-2.3.1/modules/core/src/array.cpp, line 2482
terminate called after throwing an instance of 'cv::Exception'
what(): /build/buildd/opencv-2.3.1/modules/core/src/array.cpp:2482: error: (-206) Unrecognized or unsupported array type in function cvGetMat
Aborted (core dumped)
Is it possible to read multiple images from commandline giving them as arguments? Why is it crashing?
Upvotes: 1
Views: 5432
Reputation: 11721
If you have imshow in your load loop you'll basically get a load of flickering. Just load your iamges into your array first.
for(int i=1;i<argc;i++)
{
std::cout << i << ": " << argv[i] << std::endl;
img[i-1] = imread(argv[i],0);
std::cout << "Finished reading images1" << std::endl;
}
Afterward try displaying your an image.
imshow("image",img[0]);
You might try adding a key press to loop through displaying your images. I think there is an openCV tutorial that shows this already.
I'm sure i've seen this error a couple of times, each time for a different reason. Images are just arrays, so there is something wrong with one of your images. It could be a bad jpg.
By not displaying each image in your loop, you will hopefully see if there is one image causing the issue.
Also make sure that the 'i' in your loop doesn't get to 25, i.e. an out of bounds exception. You could also putting try/catch statements in to help identify when the error occurs.
Hope that helps you narrow the issue down.
Upvotes: 1
Reputation: 20266
I don't think this compiles. You have to allocate out of the loop an array of cv::Mat
const int MAX_NUM_OF_IMG = 1024;
cv::Mat img[MAX_NUM_OF_IMG]; //You could also allocate this dynamically based on the number of arguments/the value of argc
Then, in the loop, you are breaking the boundaries, you have to change it like this:
for(int i=1;i<argc;i++) //You should also check you have not more than MAX_NUM_OF_IMG
{
img[i-1] = imread(argv[i],0); ///What is zero by the way
imshow("image",img[i]);
//Probably here you want some short sleep, or a "press a key" event
}
The number of images you get is argc-1
Then, if you want to have the name of your files stored in some txt file, you can use something like std::ifstream to parse it, as it was std::cin. There are thousands of examples, like this How To Parse String File Txt Into Array With C++
Upvotes: 2