Ask Your Question
0

RECOSTRUCTION IMAGE WITH OPENCV

asked 2015-12-14 02:53:22 -0600

baro gravatar image

updated 2020-08-13 16:16:00 -0600

Hello to all!!! I'm doing a little project for rebuild une image. I must load image from my path then. I used a grid 40x40 pixels for divide image in some little images. I must then rebuild image in order adding a red background. I think that this project is a bit useless but this is for another project. For my project is very important the division of the image and its orderly reconstruction. I post below my solution:

#include <iostream>
#include <stdio.h>
#include <math.h>

#include <opencv2\opencv.hpp>
#include "opencv\highgui.h"
#include "opencv\cv.h"

using namespace cv;
using namespace std;

Mat add_piece_of_frame(Mat, Mat, int, int);
Mat add_piece_of_frame_red(Mat, Mat, int, int);

int main(int argc, char** argv)
{
    Mat bkg_read = imread("C:\\Users\\Fabrizio\\Desktop\\frame\\VIDEO_PER_TESI\\Scene1.jpg",CV_LOAD_IMAGE_COLOR);
    IplImage * bkg = cvCloneImage( &(IplImage)bkg_read );
    namedWindow("original", 1);
    cvShowImage("original", bkg);
    cvWaitKey(3333);

    //Mat background(bkg_read);


    Mat ricostruzione[48];
    int aa[48];
    int bb[48];
    int m = 0;

    for(int a=0; a<320; a+=40)
    {
        for(int b=0; b<240; b+=40)
        {
            Mat SUPPORT (bkg_read, Rect(a,b,40,40));
            ricostruzione[m] = SUPPORT.clone();
            aa[m] = a;
            bb[m] = b;
            cout<<"coordinate:  "<<endl;
            cout<<"a:  "<<aa[m];
            cout<<"   b:  "<<bb[m]<<endl;

            m++;
        }
    }

    int A=0;

    while(A<1)
    {
        Mat output = cv::Mat::zeros(240, 320, CV_32FC3);
        Mat output_red = cv::Mat::zeros(240, 320, CV_32FC3);


        for ( int t=0; t<48; t++)
        {
            output_red = add_piece_of_frame_red(ricostruzione[t] , output_red, aa[t] , bb[t]);
        }

        IplImage * exit_red = cvCloneImage( &(IplImage)output_red );
        namedWindow("output_red", 1);
        cvShowImage("output_red",exit_red);
        cvWaitKey(3333);



        for ( int u=0; u<48; u++)
        {
            output = add_piece_of_frame(ricostruzione[u] , output, aa[u] , bb[u]);
        }

        IplImage * exit = cvCloneImage( &(IplImage)output );
        namedWindow("output", 1);
        cvShowImage("output",exit);
        cvWaitKey(3333);

    }

}

Mat add_piece_of_frame(Mat A , Mat B, int r, int c)
{
    Rect Roi(r, c, 40, 40);
    B(Roi) = B(Roi) + A.clone();
    return B;
}

Mat add_piece_of_frame_red(Mat A, Mat B, int r, int c)
{
    Scalar color = Scalar(0, 0, 255);   
    Mat mask = Mat(40, 40, CV_32FC3, color);
    Mat result;
    addWeighted(A, 0.5, mask, 0.5, 0, result, CV_32FC3); 

    Rect Roi(r, c, 40, 40);             

    B(Roi) = B(Roi) + result.clone();

    return B;
}
edit retag flag offensive close merge delete

Comments

1

Why using IplImage instead of Mat? Just for displaying? There are function that accepts cv::Mat inputs: cv::imshow(...) and cv::waitKey() for waiting for the key until going to next step

thdrksdfthmn gravatar imagethdrksdfthmn ( 2015-12-14 05:06:10 -0600 )edit

You can also use const cv::Mat& param for gaining speed. And create a new Map inside he function for returning it. Or use cv::Map& B If you want to change B

thdrksdfthmn gravatar imagethdrksdfthmn ( 2015-12-14 05:12:16 -0600 )edit
1

First of all, don't use the deprecated C-api (IplImage and cvWhatever functions). And then, what is your exact problem?

LorenaGdL gravatar imageLorenaGdL ( 2015-12-14 05:12:54 -0600 )edit

I think that my problem is the recostruction. when I use the function "add_piece_of_frame" it shows a all white image nd when I use other function it don't work and don't show anything. I suppose that image have 3 channel and when I divide it in "ricostruzione[m]" I don't have 3 channels.

when the program execute : " B(Roi) = B(Roi)+A.clone();" obtain this message:

Unhandled exception at 0x7427d8a8 in OPENCV_PROVA.exe: Microsoft C++ exception: cv::Exception at memory location 0x0017c6b8.. and in a prompt I have: opencv error: bad argument( when the input arrays in add/substract/multiply/divide functions have different types, the output array type must be explicitly specified) in cv::arithm_op, file ........\opencv\modules\core\src\arithm.cpp, line 1313 how to fix this? and the red?

baro gravatar imagebaro ( 2015-12-14 07:23:25 -0600 )edit
1

I think your problem is that you modify B when doing that B(Roi) = ... And when you are doing this a few times, then you get in that saturation case so you are getting all 255...

thdrksdfthmn gravatar imagethdrksdfthmn ( 2015-12-14 09:24:09 -0600 )edit

excuse me but with opencv I'm just the starting and I don't understand the problem. I divide one big matrix and I save orderly each single piece of matrix wich size is 40x40. After I take these pieces and I put them in a big matrix for output. I don't understand the problem of memory locations...

baro gravatar imagebaro ( 2015-12-14 11:30:45 -0600 )edit

I think that one problem is the read of matrix over the matrix size ( rows or columns)...but I think also that if the division is correct then the reconstruction must work....help meeeee

baro gravatar imagebaro ( 2015-12-14 11:36:17 -0600 )edit
1

@baro just do B(Roi) = result.clone(); and B(Roi) = A.clone();. That will assign the proper pieces. Adding the matrices is equal to adding the pixel intensities, and after a while you will end up with 255 pixel values, i.e. white pieces

LorenaGdL gravatar imageLorenaGdL ( 2015-12-14 11:37:07 -0600 )edit

excuse me but B is a zeros matrix....and I modify a piece of matrix only one time. In for cycle the Roi area change oech times. Or not?

baro gravatar imagebaro ( 2015-12-14 11:41:56 -0600 )edit
1

Yes, true, my fault. I hadn't read the code thoroughly... The error that you posted is due to such manual addings, because your read image is CV_8UC3 (I guess) and your B matrix is CV_32FC3. OpenCV does not know what type to output is you don't tell. However, as I said, don't use such sum, it makes no sense at all. About not having 3-channel images when inputting them into vector ricostruzione, I'd suggest using instead of Mat ricostruzione[48]; the following: vector<Mat> ricostruzione; ricostruzione.reserve(48);

LorenaGdL gravatar imageLorenaGdL ( 2015-12-14 11:52:23 -0600 )edit
baro gravatar imagebaro ( 2015-12-14 11:53:13 -0600 )edit

2 answers

Sort by ยป oldest newest most voted
2

answered 2015-12-14 12:42:07 -0600

LorenaGdL gravatar image

updated 2015-12-14 12:42:50 -0600

Much more optimization could be done, but at least this is working, if that is all you want:

void add_piece_of_frame(const Mat &A, Mat &B, int r, int c)
{
     Rect Roi(r, c, 40, 40);
     A.copyTo(B(Roi));
}

void add_piece_of_frame_red(const Mat &A, Mat &B, int r, int c)
{
    Rect Roi(r, c, 40, 40);
    Scalar color = Scalar(0, 0, 255);
    Mat mask = Mat(40, 40, CV_8UC3, color);
    addWeighted(A, 0.5, mask, 0.5, 0, B(Roi), CV_8UC3);
}

void main()
{
    Mat bkg_read = imread("C:\\Users\\Fabrizio\\Desktop\\frame\\VIDEO_PER_TESI\\Scene1.jpg", CV_LOAD_IMAGE_COLOR);
    imshow("original", bkg_read);
    waitKey(1);     

    Mat ricostruzione[48];
    int aa[48];
    int bb[48];
    int m = 0;

    for (int a = 0; a<320; a += 40)
    {
        for (int b = 0; b<240; b += 40)
        {
            Mat SUPPORT(bkg_read, Rect(a, b, 40, 40));
            ricostruzione[m] = SUPPORT.clone();
            aa[m] = a;
            bb[m] = b;
            cout << "coordinate:  " << endl;
            cout << "a:  " << aa[m];
            cout << "\tb:  " << bb[m] << endl;
            m++;
        }
    }

   while (true) //what is this loop for???
   {
       Mat output = cv::Mat::zeros(240, 320, CV_8UC3);
       Mat output_red = cv::Mat::zeros(240, 320, CV_8UC3);

       for (int t = 0; t<48; t++)
       {
            add_piece_of_frame_red(ricostruzione[t], output_red, aa[t], bb[t]);
       }
       imshow("output_red", output_red);
       waitKey(0);

       for (int u = 0; u<48; u++)
       {
           add_piece_of_frame(ricostruzione[u], output, aa[u], bb[u]);
       }
       imshow("output", output);
       waitKey(0);
    }
}
edit flag offensive delete link more

Comments

@LorenaGdL excuse me for the question that I think is stupid but could you tell me the correct form to write the identifiers of the two functions? thanks you soo much for your help and excuse me also for the banal questions. I'm following your code to fix my problem

baro gravatar imagebaro ( 2015-12-15 02:34:42 -0600 )edit

What do you mean by "identifiers"?

LorenaGdL gravatar imageLorenaGdL ( 2015-12-15 02:50:54 -0600 )edit

@LorenaGdL I'm using your first code that you suggest me and I obtain this error : error LNK2001: unresolved external symbol "void __cdecl add_piece_of_frame(class cv::Mat,class cv::Mat,int,int)" (?add_piece_of_frame@@YAXVMat@cv@@V12@HH@Z) error LNK2001: unresolved external symbol "void __cdecl add_piece_of_frame_red(class cv::Mat,class cv::Mat,int,int)" (?add_piece_of_frame_red@@YAXVMat@cv@@V12@HH@Z) fatal error LNK1120: 2 unresolved externals when I write:

void add_piece_of_frame(const Mat, Mat, int, int); void add_piece_of_frame_red(const Mat, Mat, int, int); int main(int argc, char** argv) { //istructions of main } void add_piece_of_frame(const Mat &A , Mat &B, int r, int c) { //corp of function } void add_piece_of_frame(const Mat &A , Mat &B, int r, int c) { //corp of function }

baro gravatar imagebaro ( 2015-12-15 06:53:46 -0600 )edit

Obviously, you need to define your functions in the header with the same parameters used in the implementation:

void add_piece_of_frame(const Mat&, Mat&, int, int); 
void add_piece_of_frame_red(const Mat&, Mat&, int, int);
LorenaGdL gravatar imageLorenaGdL ( 2015-12-15 07:25:09 -0600 )edit

@LorenaGdL Your help was very precious to me! thanks you soo much

baro gravatar imagebaro ( 2015-12-15 13:47:02 -0600 )edit

@LorenaGdL Hi LorenaGdL excuse me for my question but how I insert it in a video sequence? In others words I must read a video sequence and execute some operations and display output with some parts in red background depending on operations performed. Thanks for your time

baro gravatar imagebaro ( 2015-12-18 09:03:09 -0600 )edit
1

answered 2015-12-14 15:02:29 -0600

updated 2015-12-14 15:53:15 -0600

Although @LorenaGdL answered your question, maybe an alternative code for doing what you want will be helpful. a class named ImageCells that i posted it earlier. i hope you will understand how to use it by testing the code below ( it needs some improvements, recently i added some new features )

#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;
using namespace std;

class ImageCells
{
public:
    ImageCells( Mat img );
    ImageCells( int rows, int cols, int width, int height );
    ImageCells( int rows, int cols, Mat img );


    virtual ~ImageCells() {}

    int width() const {return m_cellwidth;}
    int height() const { return m_cellheight;}
    int cols() const { return m_cols;}
    int rows() const { return m_rows;}

    void setCellDimensions( int width, int height       );
    void setCell( int col, int row, Mat img );
    void setImage( Mat img );
    Mat getCell( int col, int row, bool clone = false );
    Mat image;

protected:
    int  m_cellwidth;
    int  m_cellheight;
    int  m_cols;
    int  m_rows;
};

ImageCells::ImageCells( Mat img )
{
    if( img.empty() )
    {
        image = Mat::zeros( 256, 256, CV_8UC3 );
    }   
    else
    image = img;

    m_cols = 1;
    m_rows = 1;
    m_cellwidth = image.cols;
    m_cellheight = image.rows;
}

ImageCells::ImageCells( int rows, int cols, int width, int height)
{
    image = Mat::zeros( rows * height, cols * width, CV_8UC3);
    m_cellwidth = width;
    m_cellheight = height;
    m_cols = cols;
    m_rows = rows;
}

ImageCells::ImageCells( int rows, int cols, Mat img )
{
    image = img;
    m_cols = cols;
    m_rows = rows;
    m_cellwidth = image.cols / m_cols;
    m_cellheight = image.rows / m_rows;
}


void ImageCells::setCellDimensions( int width, int height )
{
    m_cellwidth = width ;
    m_cellheight = height;
    m_cols = image.cols / m_cellwidth;
    m_rows = image.rows / m_cellheight;
}

void ImageCells::setCell( int col, int row, Mat img )
{
    if(img.cols == m_cellwidth & img.rows == m_cellheight)
    {
        Mat roi = image( Rect(col * m_cellwidth, row * m_cellheight, m_cellwidth, m_cellheight) );
        img.copyTo(roi);
    }
}

Mat ImageCells::getCell( int col, int row, bool clone )
{
    Mat roi = image( Rect(col * m_cellwidth, row * m_cellheight, m_cellwidth, m_cellheight) );
    if ( clone ) return roi.clone();
    return roi;
}

void ImageCells::setImage( Mat img )
{
    if(img.cols <= image.cols & img.rows <= image.rows)
    {
    img.copyTo(image);
    }
}

int main( int argc, char** argv )
{
    ImageCells cells( imread("fruits.jpg") ); // creates a ImageCells class and set its image
    cells.setCellDimensions( 40, 40 );

for(int i=0; i < cells.cols();  i++)
    for(int j =0; j < cells.rows(); j++ )
{
   Mat img = cells.getCell( i, j ); // cells.getCell( i, j, true ) returns a clone of cell
   img = img * 0.8 + Scalar( 0, 0, rand()&127 );
   imshow("cells.image",cells.image);
   waitKey();
}

for(int i=0; i < cells.cols(); i++)
    for(int j =0; j < cells.rows(); j++ )
{
    imshow("cells",cells.getCell(i,j)); // here you see how to use  getCell
    waitKey();
}
    return 0;
}

Result Image ( willingly i added random red for each cell )

image description

edit flag offensive delete link more

Comments

a similar class implementation can be found here

sturkmen gravatar imagesturkmen ( 2016-01-08 03:52:38 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2015-12-14 02:53:22 -0600

Seen: 499 times

Last updated: Dec 14 '15