Search code examples
javaopencvopencv3.3

Join different sized images with ROI


At the first contact with Java OpenCV (3.3.1, windows 8 x64) I'm trying to join two different size images with ROI dynamically. Here a bit of my code:

Mat _mat = Utils.imageFileToMat(new File("angelina_jolie.jpg")); //Angelina's face
Mat grayMat = new Mat();
Imgproc.cvtColor(_mat, grayMat, Imgproc.COLOR_BGR2GRAY);
Rect rect = new Rect(new Point(168, 104), new Point(254, 190)); //Angelina's eye ROI
Mat truncated = _mat.submat(rect); //Angelina's eye mat

Mat merge = _mat.clone();
truncated.copyTo(merge);

//show _mat
//show truncated
//show merge

What I want to see is Angelina Jolie with her eye on grayscale.

What I see is assertions or the truncated image only (just the eye).

I tried with copyTo(mat, mask), setOf, and a lot of things but always get a new assertion.

Should I change the size of truncated to the size of mat to match sizes? how can I do that programmatically?


Solution

  • Mat::copyTo documentation:

    The method copies the matrix data to another matrix. Before copying the data, the method invokes :

    m.create(this->size(),this->type());
    

    so that the destination matrix is reallocated if needed. While m.copyTo(m); works flawlessly, the function does not handle the case of a partial overlap between the source and the destination matrices.

    When the operation mask is specified, if the Mat::create call shown above reallocates the matrix, the newly allocated matrix is initialized with all zeros before copying the data.

    @param m Destination matrix. If it does not have a proper size or type before the operation, it is reallocated.

    Since you're your src and dst images don't have the same size and channels, the destination image is reallocated and initialized with zeros. To avoid that make sure both images have same dimensions and number of channels.

    Imgproc.cvtColor(grayMat, grayMat, Imgproc.COLOR_GRAY2BGR);
    

    Now create a mask:

    Mat mask = new Mat(_mat.size(), CvType.CV_8UC1, new Scalar(0));
    Imgproc.rectangle(mask, new Point(168, 104), new Point(254, 190),new Scalar(255));
    // copy gray to _mat based on mask
    Mat merge = _mat.clone();
    grayMat.copyTo(merge,mask);