Robotic Vn
Robotic Vn

Reputation: 577

Copy Mat in opencv

I try to copy a image to other image using opencv, but I got a problem. Two image is not the same, like this:

enter image description here

This is the code I used:

#include <opencv2\opencv.hpp>

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <cmath>
#include <iostream>
#include <opencv2\opencv.hpp>
int main()
{
    cv::Mat inImg =    cv::imread("C:\\Users\\DUY\\Desktop\\basic_shapes.png");  
    //Data point copy  
    unsigned char * pData = inImg.data;  

    int width = inImg.rows;  
    int height = inImg.cols;  

    cv::Mat outImg(width, height, CV_8UC1);  
    //data copy using memcpy function  
    memcpy(outImg.data, pData, sizeof(unsigned char)*width*height);  

   //processing and copy check  
   cv::namedWindow("Test");  
   imshow("Test", inImg);  

   cv::namedWindow("Test2");  
   imshow("Test2", outImg);  

   cvWaitKey(0);  
}

Upvotes: 24

Views: 56600

Answers (6)

Benjamin Lee
Benjamin Lee

Reputation: 39

Mat source = imread("1.png", 0);
Mat dest;
source.copyTo(dest);

Upvotes: 0

David Safrastyan
David Safrastyan

Reputation: 785

Simply use .clone() function of cv::Mat:

cv::Mat source = cv::imread("basic_shapes.png");
cv::Mat dst = source.clone();

This will do the trick. You are making an image with one channel only (which means only shades of gray are possible) with CV_8UC1, you could use CV_8UC3 or CV_8UC4 but for simply copying stick with the clone function.

Upvotes: 48

Sagar Patel
Sagar Patel

Reputation: 852

Here is a simple code to copy image.

 #include <opencv2/opencv.hpp>  
 #include <opencv2/highgui/highgui.hpp>  
 #include <opencv2/imgproc/imgproc.hpp>  
 #include <cmath> 
 int main()  
 {  
    cv::Mat inImg = cv::imread("1.jpg");  

    cv::Mat outImg = inImg.clone();   

   cv::namedWindow("Test");  
   imshow("Test", inImg);

   cv::namedWindow("Test2");  
   imshow("Test2", outImg);

   cvWaitKey(0);  
}

Upvotes: 2

Miki
Miki

Reputation: 41776

You actually don't want to copy the data, since you start with a RGB CV_8UC3 image, and you want to work on a grayscale CV_8UC1 image.

You should use cvtColor, that will convert your RGB data into grayscale.

#include <opencv2\opencv.hpp>
#include <iostream>

using namespace cv;

int main()
{
    Mat inImg = cv::imread("C:\\Users\\DUY\\Desktop\\basic_shapes.png"); // inImg is CV_8UC3 
    Mat outImg;
    cvtColor(inImg, outImg, COLOR_RGB2GRAY); // Now outImg is CV_8UC1

    //processing and copy check  
    imshow("Test", inImg);  
    imshow("Test2", outImg);  
    waitKey();  
}

With a simple memcopy you're copying a sequence of uchar like this:

BGR BGR BGR BGR  ...

into an image that expects them to be (G for gray):

G G G G ...

and that's is causing your outImg to be uncorrect.

Your code will be correct if you define outImage like:

cv::Mat outImg(width, height, CV_8UC3);  // Instead of CV_8UC1

Upvotes: 5

RyanP
RyanP

Reputation: 1918

Your original image is in color. cv::Mat outImg(width, height, CV_8UC1); says that your new image is of data type CV_8UC1 which is an 8-bit grayscale image. So you know that is not correct. Then you try to copy the amount of data from the original image to the new image that corresponds to total pixels * 8-bits which is at best 1/3 of the actual image (assuming the original image was 3 color, 8-bits per color, aka a 24-bit image) and perhaps even 1/4 (if it had an alpha channel, making it 4 channels of 8-bits or a 32-bit image).

TLDR: you're matrices aren't the same type, and you are making assumptions about the size of the data to be copied off of an incorrect, and incorrectly sized type.

Upvotes: 2

Chris Maes
Chris Maes

Reputation: 37842

the best way is to use the opencv clone method:

cv::Mat outImg = inImg.clone();

Upvotes: 3

Related Questions