I have an Image in a cv::Mat as a face, I need the whole image in a cv::Rect object
I couldn't find how it is done
That or , if possible ,creating the Rect from an image in my directory
you don't convert a cv::Mat to a cv::Rect.
you want the part of the image inside that Rect ?
Mat roi = Mat(img,rect);
will give you the cropped region
cv::Mat can't directly give you a cv::Rect, but you can create your
own using the size() method of cv::Mat, and by assuming that the starting point of the cv::Rect is (0,0)
cv::Mat image;
// load your image into the cv::Mat
...
// now create the cv::Rect from the cv::Mat
cv::Rect rect = cv::Rect(0, 0, image.size().width, image.size().height);
Although, as #berak says, you can't convert a cv::Mat to a cv::Rect, I am guessing you want something like this (untested).
cv::Mat face; // you already have this with some data in it
cv::Mat image; // you already have this with some data in it
cv::Rect rect(x, y, w, h); // some place in image where you want face
// copy face into rectange within image
cv::resize(face, image(rect), cv::Size(rect.width, rect.height));
Related
I use openCV to recognize contours. Now I want to create a new binary mat containing all coordinates of this contour.
Canny edge detection applied
found contour's (red one is the one I'd like to use)
just coordinates inside contour are drawn into new mat
This is what I've got so far:
vector<cv::Point> contour; // red marked contour;
cv::Rect boundingBox = cv::boundingRect(contour);
Mat newMat;
vector<cv::Point> insideContour;
for (int i=0; i<contour.size(); i++) {
// get all coordinates inside of contour
// insideContour.push_back(?)
}
for (int y=0; y<boundingBox.height; y++) {
for (int x=0; x<boundingBox.width; x++) {
// newMat
}
}
Any help how to go on would be really appreciated because I'm absolutely clueless.
Try this. For simplicity cv::Point(250, 219) is a point inside the red contour, use Haar to find bounding box and it's center in reality.
cv::Mat image = imread("Smiley.jpg");
cv::Mat image2 = imread("Smiley2.jpg");
// subtract images and floodfill to prepare red mask
Mat red_contour, red_mask, maskMat, outputMat;
subtract(image2, image, red_contour);
threshold(red_contour, red_mask, 100, 255, THRESH_BINARY);
int filling = cv::floodFill(red_mask, cv::Point(250, 219), cv::Scalar(0, 0, 255), (cv::Rect*)0, cv::Scalar(), cv::Scalar(), 4);
//prepare a grey mask
cv::cvtColor(red_mask, maskMat, CV_BGR2GRAY);
threshold(maskMat, maskMat, 0, 255, THRESH_BINARY);
// use mask to crop original image
image.copyTo(outputMat, maskMat);
cv::namedWindow("Image");
cv::imshow("Image", outputMat);
cv::waitKey();
return 0;
For example, I create
Mat mat1 = Mat::zeros(Size(100, 100), CV_8UC3);
and fill each pixel with (0, 255, 255), which is supposed to be red in hsv.
However, if I imshow this mat, this will be printed as a BGR image and is not red.
How do I make this mat hsv format and setting (0, 255, 255) result in red?
imshow assumes that the image you pass to it is in BGR color space. However, you can create a small function that does your imshow of HSV images.
void imshowHSV(std::string& name, cv::Mat& image)
{
cv::Mat hsv;
cv:cvtColor(image, hsv, CV_HSV2BGR);
cv::imshow(name, hsv);
}
But beware! this will convert and create a copy of the image, if you over use it it may have quite some overhead :)
I write a simple app in OpenCV that delete black background of an image and save it with white background in JPG. However, it's always saved with black background.
This is my code:
Mat Imgsrc = imread("../temp/temp1.jpg",1) ;
mat dest;
Mat temp, thr;
cvtColor(Imgsrc, temp, COLOR_BGR2GRAY);
threshold(temp,thr, 0, 255, THRESH_BINARY);
Mat rgb[3];
split(Imgsrc,rgb);
Mat rgba[4] = { rgb[0],rgb[1],rgb[2],thr };
merge(rgba,4,dest);
imwrite("../temp/r5.jpg", dest);
You can simply use setTo with a mask to set some pixels to a specific value according to a mask:
Mat src = imread("../temp/temp1.jpg",1) ;
Mat dst;
Mat gray, thr;
cvtColor(src, gray, COLOR_BGR2GRAY);
// Are you sure to use 0 as threshold value?
threshold(gray, thr, 0, 255, THRESH_BINARY);
// Clone src into dst
dst = src.clone();
// Set to white all pixels that are not zero in the mask
dst.setTo(Scalar(255,255,255) /*white*/, thr);
imwrite("../temp/r5.jpg", dst);
Also a few notes:
You can directly load an image as grayscale using: imread(..., IMREAD_GRAYSCALE);
You can avoid to use all those temporary Mats.
Are you sure you want to use 0 as threshold value? Because in this case you can avoid entirely to apply theshold, and set to white all pixels that are 0 in the grayscale image: dst.setTo(Scalar(255,255,255), gray == 0);
This is how I'd do:
// Load the image
Mat src = imread("path/to/img", IMREAD_COLOR);
// Convert to grayscale
Mat gray;
cvtColor(src, gray, COLOR_BGR2GRAY);
// Set to white all pixels that are 0 in the grayscale image
src.setTo(Scalar(255,255,255), gray == 0)
// Save
imwrite("path/to/other/img", src);
How can i use cvGet2D and cvSet2D to get this result:
Code:
std::string path = "C:\\image.jpg";
cv::Mat img = cv::imread (path);
CvScalar scal = cvGet2D(m, 0, 2);
cvSet2D(m, 0, 2, new_value);*/
cv::imshow( "Result window", img );
Since you know the coordinates of the top-left and bottom-right rectangle corners:
Point tl(250, 250);
Point br(350, 280);
You can draw a black filled rectangle:
rectangle(img, Rect(tl, br), Scalar(0,0,0), CV_FILLED);
Result (note that my image has different size from yours, so results appear slightly different):
Code:
#include <opencv2\opencv.hpp>
using namespace cv;
int main()
{
// Load image
Mat3b img = imread("path_to_image");
// Set top-left and bottom-right rectangle points
Point tl(250, 250);
Point br(350, 280);
// Draw a filled rect
rectangle(img, Rect(tl, br), Scalar(0,0,0), CV_FILLED);
// Show result
imshow("Result", img);
waitKey();
return 0;
}
Note
cvSetXD and cvGetXD are old style C syntax. You should never mix obsolete C syntax and C++ syntax. If you want to access pixel values in a Mat, you should use the at function.
Suppose my objective is to extract contours from an initial image. I performed this operations using OpenCV:
cv::Mat gray, edges;
cv::cvtColor(image, gray, CV_BGRA2GRAY);
cv::Canny(gray, edges, 100, 300, 3);
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(edges, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
Now the contour is contained in an array of Points. I want to rebuild a cv::Mat structure having the same dimensions as the initial image, so as to emphasize the contour by superimposing it to the image.
In particular, I am not interested in drawing immediately the contour. I will perform the following operations:
extract the contour
dilate the contour
superimpose the contour on the image (as you do in edge sharpening)
Thus, the contour has to be a matrix of the same size of the input image.
How can I do that?
Thanks in advance.
You can re-built a Matrix
Mat image_contours_grayscale = Mat::zeros(gray.size(),gray.type());
Scalar color(255);
drawContours( image_contours_grayscale, contours,-1,color,1);
I'm not sure if drawContours works with grayscale image, but if it doesn't, you can try this
Mat image_contours_color = Mat::zeros(image.size(),image.type());
Scalar color(255,255,255);
drawContours( image_contours_color, contours,-1,color,1);
Mat image_contours_grayscale;
cv::cvtColor(image_contours_color, image_contours_grayscale, CV_BGRA2GRAY);
image_contours_grayscale should be a grayscale image, all black with the contours in white.
Let me know if this works, I didn't have the occasion to test this solution !