I have an image converted in a CvMat
Matrix say CVMat source
. Once I get a region of interest from source
I want the rest of the algorithm to be applied to that region of interest only. For that I think I will have to somehow crop the source
matrix which I am unable to do so. Is there a method or a function that could crop a CvMat
Matrix and return another cropped CvMat
matrix? thanks.

- 4,167
- 3
- 25
- 30

- 957
- 2
- 8
- 14
-
1Do you want it in the pre 2.0 c style or the post 2.0 c++ style? please re-tag your question according to your answer – Boaz Nov 25 '11 at 13:58
6 Answers
OpenCV has region of interest functions which you may find useful. If you are using the cv::Mat
then you could use something like the following.
// You mention that you start with a CVMat* imagesource
CVMat * imagesource;
// Transform it into the C++ cv::Mat format
cv::Mat image(imagesource);
// Setup a rectangle to define your region of interest
cv::Rect myROI(10, 10, 100, 100);
// Crop the full image to that image contained by the rectangle myROI
// Note that this doesn't copy the data
cv::Mat croppedImage = image(myROI);

- 8,030
- 4
- 37
- 56
-
6
-
7It means it only creates a reference to that image region and not a copy. This means that if you change the croppedImage it also changes the imagesource. If you do not want this behavior you can create a copy explicitly. – Rui Marques Feb 13 '13 at 20:11
-
What if I want an ellipse region instead of a Rectangle region of interest? – Sohaib Oct 07 '13 at 15:07
-
2@Sohaib Then we need to use what we call a "mask", which is usually available as an extra parameter on processing functions. – Samuel Audet May 02 '15 at 22:27
-
hey i have doubt ,my image is of size(3264*2448).I am able to plot a point.But the point x OR y is not in device coordinates(eg 2400,1864 etc).Can someone help how to convert the cv::Point to device coordinates – Mukesh Jun 03 '15 at 09:53
-
-
Could you clarify what the in parameters to the cv::Rect are? From what I found its x, y, width, height. Is that correct? – Björn Larsson Feb 19 '18 at 10:33
-
2
-
what about OpenCV4Android? `val croppedMatGray = Mat(matGray, rect)` - it's not copy too? just reference? – user924 Jun 14 '19 at 10:38
I know this question is already solved.. but there is a very easy way to crop. you can just do it in one line-
Mat cropedImage = fullImage(Rect(X,Y,Width,Height));

- 1,676
- 5
- 26
- 43
-
3From where do you get the `fullImage()` function? EDIT: Nevermind, it's the `cv::Mat`-image itself... – mozzbozz Jan 11 '18 at 15:04
-
1
-
1It says above that this does not copy the contents, just a reference. Is this true? – KansaiRobot Jan 04 '21 at 08:34
To get better results and robustness against differents types of matrices, you can do this in addition to the first answer, that copy the data :
cv::Mat source = getYourSource();
// Setup a rectangle to define your region of interest
cv::Rect myROI(10, 10, 100, 100);
// Crop the full image to that image contained by the rectangle myROI
// Note that this doesn't copy the data
cv::Mat croppedRef(source, myROI);
cv::Mat cropped;
// Copy the data into new matrix
croppedRef.copyTo(cropped);

- 361
- 3
- 4
To create a copy of the crop we want, we can do the following,
// Read img
cv::Mat img = cv::imread("imgFileName");
cv::Mat croppedImg;
// This line picks out the rectangle from the image
// and copies to a new Mat
img(cv::Rect(xMin,yMin,xMax-xMin,yMax-yMin)).copyTo(croppedImg);
// Display diff
cv::imshow( "Original Image", img );
cv::imshow( "Cropped Image", croppedImg);
cv::waitKey();

- 4,178
- 8
- 41
- 55
-
1This add nothing to the answer already provided. Also you're missing a semicolon and have incorrect variables names. BTW, you can do this with `Mat crop = img(Rect(...)).clone()` – Miki Feb 18 '16 at 21:48
-
Fixed typos. I do think it adds in the sense that it does everything in one line. As for the clone or copyTo in this case I guess it's just what one favors. – Reed Richards Feb 18 '16 at 22:03
I understand this question has been answered but perhaps this might be useful to someone...
If you wish to copy the data into a separate cv::Mat object you could use a function similar to this:
void ExtractROI(Mat& inImage, Mat& outImage, Rect roi){
/* Create the image */
outImage = Mat(roi.height, roi.width, inImage.type(), Scalar(0));
/* Populate the image */
for (int i = roi.y; i < (roi.y+roi.height); i++){
uchar* inP = inImage.ptr<uchar>(i);
uchar* outP = outImage.ptr<uchar>(i-roi.y);
for (int j = roi.x; j < (roi.x+roi.width); j++){
outP[j-roi.x] = inP[j];
}
}
}
It would be important to note that this would only function properly on single channel images.

- 49
- 1
- 5
-
This helped me a lot. I created a version that extracts ROIs from 16 bit per pixel images. https://gist.github.com/fernandoc1/e69e4c09d0bf4b09076af40c06b13450 – Fernando Sep 24 '19 at 21:54
You can easily crop a Mat using opencv funtions.
setMouseCallback("Original",mouse_call);
The mouse_call
is given below:
void mouse_call(int event,int x,int y,int,void*)
{
if(event==EVENT_LBUTTONDOWN)
{
leftDown=true;
cor1.x=x;
cor1.y=y;
cout <<"Corner 1: "<<cor1<<endl;
}
if(event==EVENT_LBUTTONUP)
{
if(abs(x-cor1.x)>20&&abs(y-cor1.y)>20) //checking whether the region is too small
{
leftup=true;
cor2.x=x;
cor2.y=y;
cout<<"Corner 2: "<<cor2<<endl;
}
else
{
cout<<"Select a region more than 20 pixels"<<endl;
}
}
if(leftDown==true&&leftup==false) //when the left button is down
{
Point pt;
pt.x=x;
pt.y=y;
Mat temp_img=img.clone();
rectangle(temp_img,cor1,pt,Scalar(0,0,255)); //drawing a rectangle continuously
imshow("Original",temp_img);
}
if(leftDown==true&&leftup==true) //when the selection is done
{
box.width=abs(cor1.x-cor2.x);
box.height=abs(cor1.y-cor2.y);
box.x=min(cor1.x,cor2.x);
box.y=min(cor1.y,cor2.y);
Mat crop(img,box); //Selecting a ROI(region of interest) from the original pic
namedWindow("Cropped Image");
imshow("Cropped Image",crop); //showing the cropped image
leftDown=false;
leftup=false;
}
}
For details you can visit the link Cropping the Image using Mouse

- 61
- 5