copyto - Cómo recortar un CvMat en OpenCV?
opencv mat rgb (6)
Tengo una imagen convertida en CvMat
Matrix, dice CVMat source
. Una vez que obtenga una región de interés de la source
, quiero que el resto del algoritmo se aplique únicamente a esa región de interés. Para eso, creo que tendré que recortar de algún modo la matriz de source
, lo que no puedo hacer. ¿Hay algún método o función que pueda recortar una Matriz CvMat
y devolver otra matriz recortada CvMat
? Gracias.
Entiendo que esta pregunta ha sido respondida, pero quizás esto podría ser útil para alguien ...
Si desea copiar los datos en un objeto cv :: Mat por separado, podría utilizar una función similar a esta:
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];
}
}
}
Sería importante tener en cuenta que esto solo funcionaría correctamente en imágenes de un solo canal .
OpenCV tiene funciones de región de interés que pueden serle útiles. Si está utilizando cv::Mat
, podría usar algo como lo siguiente.
// 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);
Para crear una copia del cultivo que queremos, podemos hacer lo siguiente,
// 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();
Para obtener mejores resultados y robustez frente a los diferentes tipos de matrices, puede hacer esto además de la primera respuesta, que copie los datos:
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);
Puede recortar fácilmente una estera usando funciones de OpenCV.
setMouseCallback("Original",mouse_call);
El mouse_call
se da a continuación:
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;
}
}
Para más detalles, puede visitar el enlace Recortar la imagen usando el mouse
Sé que esta pregunta ya está resuelta ... pero hay una manera muy fácil de cosechar. solo puedes hacerlo en una línea-
Mat cropedImage = fullImage(Rect(X,Y,Width,Height));