Ask Your Question
5

read multiple images from folder and concat, display images in single window opencv c++, visual studio 2010

asked 2013-05-24 12:08:21 -0500

SindhuMegha gravatar image

updated 2013-05-24 16:08:10 -0500

Guanta gravatar image

Hi,I' m new to opencv c++, I need to concat multiple images and display it in single window. Here the source code i hv done,I m reading images from folder and resizing images to thumbnail size,Now i want to concat thumbnail sized multile images and copy into Big Image(Mat image). But my source code, multiple images are not concatinating, What's wrong with the code?..Pls help me...

FILE* f;
using namespace cv;
using namespace std;
int main()
{
    IplImage *desimg,*srcimg;
    Mat output,src,tumbnail1;
    srcimg=cvLoadImage("E:\\images\\img\\b1.jpg",1);
    output=cvCreateMat(srcimg->width,srcimg->height,3);

    //load multiple images....................
    //File finding objects
    struct _finddata_t c_file;

    long hFile;
    int value_max,value,height,width;
    char imageDirectory[] = "E:\\images\\img";
    char imageFileType[] = "jpg";
    char fullImagePath[1000];
    char buffer[1000];  
    sprintf(buffer,"%s\\*.%s", imageDirectory, imageFileType);
    hFile = _findfirst( buffer, &c_file );
    /*Check to make sure that there are files in directory*/
    if( hFile == -1L )
        printf( "No %s files in current directory!\n", imageFileType );
    else
    {   
        // List all files in directory
        printf( "Listing of files:\n" );
        // Loop through all images of imageFileType
        do  
        {   
            // Show file name
            printf( "\nOpening File: %s \n", c_file.name);

            sprintf(fullImagePath,"%s\\%s", imageDirectory, c_file.name);

            // Load image
            desimg = cvLoadImage(fullImagePath);

            Mat src1=cv::cvarrToMat(desimg); //convert ipl img to mat
            Mat src2=cv::cvarrToMat(srcimg);

            cv::Mat tumbnails2;

            tumbnail1=cvCreateMat(src1.rows/10,src1.cols/10,3);
            tumbnails2=cvCreateMat(src2.rows/10,src2.cols/10,3);

            cv::resize(src1, tumbnails2,tumbnails2.size());
            cv::resize(src2, tumbnail1,tumbnail1.size());
            //tumbnails1.push_back(tumbnails2);
            vconcat(tumbnail1,tumbnails2,output);

        } while( _findnext( hFile, &c_file ) == 0 );

        // Close file finder object
        _findclose( hFile );
    }

    imshow("concatenation of multiple images",output);
    waitKey(0);

    return 0;
}
edit retag flag offensive close merge delete

1 answer

Sort by » oldest newest most voted
5

answered 2013-05-24 16:04:18 -0500

Guanta gravatar image

So you have a bunch of images and want to arange them in one large image. Let's say you put all your images first to a vector (images) and you want a specific number of columns (cols) and maybe some gap between the images (min_gap_size) then you can arrange them with the following method:

cv::Mat createOne(std::vector<cv::Mat> & images, int cols, int min_gap_size)
{
    // let's first find out the maximum dimensions
    int max_width = 0;
    int max_height = 0;
    for ( int i = 0; i < images.size(); i++) {
        // check if type is correct 
        // you could actually remove that check and convert the image 
        // in question to a specific type
        if ( i > 0 && images[i].type() != images[i-1].type() ) {
            std::cerr << "WARNING:createOne failed, different types of images";
            return cv::Mat();
        }
        max_height = std::max(max_height, images[i].rows);
        max_width = std::max(max_width, images[i].cols);
    }
    // number of images in y direction
    int rows = std::ceil(images.size() / cols);

    // create our result-matrix
    cv::Mat result = cv::Mat::zeros(rows*max_height + (rows-1)*min_gap_size,
                                    cols*max_width + (cols-1)*min_gap_size, images[0].type());
    size_t i = 0;
    int current_height = 0;
    int current_width = 0;
    for ( int y = 0; y < rows; y++ ) {
        for ( int x = 0; x < cols; x++ ) {
            if ( i >= images.size() ) // shouldn't happen, but let's be safe
                return result;
            // get the ROI in our result-image
            cv::Mat to(result,
                       cv::Range(current_height, current_height + images[i].rows),
                       cv::Range(current_width, current_width + images[i].cols));
            // copy the current image to the ROI
            images[i++].copyTo(to);
            current_width += max_width + min_gap_size;
        }
        // next line - reset width and update height
        current_width = 0;
        current_height += max_height + min_gap_size;
    }
    return result;
}

I hope it is clear what you have to do (in your do-while-loop you add all your matrices to a vector and afterwards you call createOne()).

Also note that you kinda mix the C-API of OpenCV with the C++ one, I recommend to switch completely to C++, i.e. imread() instead of cvLoadImage(), replace cvCreateMat to the proper Mat's and what does actually vconcat() do?

edit flag offensive delete link more

Comments

Thanks a lot:).. Its working perfectly... vconcat & hconcat are functions of opencv to concat two images horizantally and vertical........

SindhuMegha gravatar imageSindhuMegha ( 2013-06-12 03:12:22 -0500 )edit

Cool, I haven't known vconcat and hconcat so far, thx! Btw, please mark the answer as correct, if it solved your problem.

Guanta gravatar imageGuanta ( 2013-06-12 03:33:04 -0500 )edit

please provide the altogether code. Help will be appreciated.

ayesha gravatar imageayesha ( 2013-12-15 04:19:51 -0500 )edit

Its works perfect!!! Thanks!

kitab15 gravatar imagekitab15 ( 2014-03-26 09:44:48 -0500 )edit

please provide altogether code for displaying all images in one window.

bharath gravatar imagebharath ( 2014-06-20 13:05:18 -0500 )edit

please help how to display all images in one window i tried the above code by keeping all images to a vector and calling createOne function but for me displaying only first and last images only in output window.

bharath gravatar imagebharath ( 2014-06-22 08:47:46 -0500 )edit

Sry, but I don't see your problem. Example usage:

std::vector<cv::Mat> my_images;

my_images.push_back( cv::imread('path/to/first/image1.jpg') );
my_images.push_back( cv::imread('path/to/first/image2.jpg') );
my_images.push_back( cv::imread('path/to/first/image3.jpg') );
cv::Mat to_show =  createOne(my_images, 1, 5);
cv::imshow("show my images", to_show);
Guanta gravatar imageGuanta ( 2014-06-22 13:20:50 -0500 )edit

I found a small error in your code. If I have 3 images and 2 columns, the number of rows is calculated wrong. Because images.size()/cols is an int division. You should force to be a float or double division. It can be done like that:

int rows = std::ceil(images.size() / (float) cols);
Derzu gravatar imageDerzu ( 2018-05-05 11:01:47 -0500 )edit
Login/Signup to Answer

Question Tools

Stats

Asked: 2013-05-24 12:08:21 -0500

Seen: 17,862 times

Last updated: May 24 '13