Copy Mat in opencv
Asked Answered
A

6

24

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);  
}
Analysis answered 16/7, 2015 at 15:32 Comment(0)
B
48

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.

Benzene answered 16/7, 2015 at 15:37 Comment(1)
Which one better option either clone or copyTo of image?Leboff
M
5

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
Medicable answered 16/7, 2015 at 15:46 Comment(0)
U
3

the best way is to use the opencv clone method:

cv::Mat outImg = inImg.clone();
Undistinguished answered 16/7, 2015 at 15:35 Comment(3)
thank for your help, but I want to use Mat.data as an array of unsigned char. I need to do something ralated to thisAnalysis
in that case you might need to convert to CV_8UC3 format, that's more complicated...Undistinguished
open cv has functions to convert matrices between data types (8UC1 -> 8UC3, 8UC3 -> 8UC1, etc). You need to make sure that before you use a raw pointer to the matrix data you have converted that matrix to the data type you will use the pointer as.Natator
N
2

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.

Natator answered 16/7, 2015 at 15:40 Comment(0)
W
2

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);  
}
Widthwise answered 13/8, 2015 at 9:22 Comment(0)
R
1
Mat source = imread("1.png", 0);
Mat dest;
source.copyTo(dest);
Rampage answered 3/3, 2022 at 2:29 Comment(1)
While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value.Hardy

© 2022 - 2024 — McMap. All rights reserved.