I'm new to image processing and development. I have pixel coordinates of an image. By connecting each coordinate can be obtained a triangle. I want to extract pixels inside pixels of giving coordinates (pixels within a triangle)
Cordinates as follows.
1(x,y) -> (146 , 548)
2(x,y) -> (155, 548)
3(x,y) -> (149.6 , 558.1)
How do i take pixels that are inbound of above coordinates. Any help is appreciated. Thank you.
You should apply mask on your image.
Example code:
First you should load your image:
//load default image
Mat image = cv::imread("/home/fabio/code/lena.jpg", cv::IMREAD_GRAYSCALE);
Then create a mask for your image and apply the triangle points to the mask.
//mask image definition
cv::Mat mask = cv::Mat::zeros(image.size(), image.type());
//triangle definition (example points)
vector<Point> points;
points.push_back( Point(100,70));
points.push_back( Point(60,150));
points.push_back( Point(190,120));
//apply triangle to mask
fillConvexPoly( mask, points, Scalar( 255 ));
After that your mask will look like this:
Finally create the final image applying the mask to the original image:
//final image definition
cv::Mat finalImage = cv::Mat::zeros(image.size(), image.type());
image.copyTo(finalImage, mask);
Result:
Is that what you're looking for?
There is a thread talking about this, the solution given there is easily applicable to your case, just replacing the shape used in the example provided.
Here is the link : opencv-binary-image-mask-for-image-analysis-in-c
Related
I've got a Mat image which is a binary mask that I segmented and a cv::Rect that identifies an specific region. When I get the contours of the binary mask the image is like this:
Binary Mask
Contours generated
I would like to fill in the mask the region that intersects with the rectangle. How would I do that?
Thanks in advance.
There is way simpler than #ZdaR's solution: using Regions Of Interest (ROI) which directly selects the bounding rectangle region to process.
cv::Rect boundingRect(/* x, y, width, height */);
contours_image(boundingRect).setTo(255, binary_image(boundingRect));
Here, I select each region with operator parenthesis contours_image(boundingRect) and binary_image(boundingRect), and use the binary image part as a mask to set all corresponding pixels to 255.
A good choice would be to use cv::min() with the binary image and another cv::Mat() with the area under cv::Rect() painted as white. It will filter out the desired portion under the Rect as:
// Create a grayscale canvas with black background
cv::Mat canvas = cv::Mat(binary_img.size(), CV_8UC1, cv::Scalar(0));
// I created a dummy rect replace it with original rect coordinates.
cv::Rect boundingRect = cv::Rect(100, 100, 200, 200);
// Draw filled rect onto the black canvas with white color
cv::rectangle(binary_image, boundingRect, cv::Scalar(255), -1);
// Take the min of binary image and canvas to filter out the contours
cv::min(binary_image, canvas, binary_image);
EDIT:
If you want to filter the contours which intersect the cv::Rect, then you need to iterate over each contour, calculate the boundingRect and check if it intersects the given rect.
for (int i=0; i<contours.size(); i++) {
if ((cv::boundingRect(contours[i]) & boundingRect).area() > 0) {
// Your desired contours found.
}
}
I have a 200x200 pixels image and I want to keep only the data for a certain region inside it.
Check the following image:
The whole out square is 200x200 pixels.I want to remove from it the smaller square(white).So ,keep only the information that is included in the blue area.But , I want to keep the 200x200 dimensions.
I tried:
Mat whiteArea;
whiteArea = ImageInitial( Range(50,200) , Range(50,200) );
Size size(200,200);
Mat dst;
resize(whiteArea,dst,size);
Mat FinalImage;
subtract(ImageInitial,dst,FinalImage);
I am resizing the white area because I want to substract it from the initial image.
My problem is that it gives me the initial image.
Maybe the resize is the problem .but then how to substract 2 different sized images?
try to use subimages or use a mask:
// use a roi (nice if your target area is rectangular and you know the position)
Rect whiteArea = Rect(50,50, 200,200); // creates a roi of the inner rect
Mat FinalImage = ImageInitial.clone();
// now set the roi area to zero:
FinalImage (whiteArea).setTo(Scalar(0,0,0));
// or FinalImage(whiteArea) = FinalImage(whiteArea) - FinalImage(whiteArea);
imshow("version 1 with subimage", FinalImage);
waitkey(0);
// or use a mask (nice if that region can has arbitrary shape etc and you have to extract it first):
Scalar lowerColorBound = Scalar(x,y,z); //some BGR values to find the color you want to eliminate
Scalar upperColorBound = Scalar(a,b,c); //some BGR values to find the color you want to eliminate
Mat mask;
inRange(ImageInitial, lowerColorBound, upperColorBound mask)
// use the mask for subtraction:
subtract(ImageInitial, ImageInitial, FinalImage , mask);
imshow("version 2 with mask", FinalImage);
waitkey(0);
Mask image
Result image
Expected image
Is there any function to draw a rectangle with mask image using opencv? i have attached the expected image. Please help me. thanks in advance.
I think your asked question isn't quite clear, but if the first image is your original image (circle), the second one (rectangle) is your binary mask image, and you want to apply that mask on the original image, than you can apply the mask as followed:
inputMat.copyTo(outputMat, maskMat);
Src.: https://stackoverflow.com/a/18161322/4767895
If you haven't already created a binary mask, do it this way:
Create a mask with the same size as your original image (set all zero), and draw a filled rectangle (set all one) with specific size in it.
cv::Mat mask = cv::Mat::zeros(Rows, Cols, CV_8U); // all 0
mask(Rect(StartX,StartY,Width,Height)) = 1; //make rectangle 1
Src.: https://stackoverflow.com/a/18136171/4767895
Feel free to response if I misunderstood your question.
Try using Boolean Operation provided in Opencv
Please refer to this code (source). I have added all the bitwise operation in case you need any.
int main( )
{
Mat drawing1 = Mat::zeros( Size(400,200), CV_8UC1 );
Mat drawing2 = Mat::zeros( Size(400,200), CV_8UC1 );
drawing1(Range(0,drawing1.rows),Range(0,drawing1.cols/2))=255; imshow("drawing1",drawing1);
drawing2(Range(100,150),Range(150,350))=255; imshow("drawing2",drawing2);
Mat res;
bitwise_and(drawing1,drawing2,res); imshow("AND",res);
bitwise_or(drawing1,drawing2,res); imshow("OR",res);
bitwise_xor(drawing1,drawing2,res); imshow("XOR",res);
bitwise_not(drawing1,res); imshow("NOT",res);
waitKey(0);
return(0);
}
I have an image from which I want to get a vertical ROI, apply some transformations and add to another image.
I read a lot of questions and answer on StackOverflow and other forums, but I'm still stuck with this problem. For the moment I'm using the C interface of OpenCV, but I could use the C++ one if needed (I would have to write a conversion function, since I'm working with CGImageRef in Cocoa).
To get from the top image (see below) to the bottom image, I guess I have to :
Get the ROI on the first image ;
Scale it down ;
Get the intersection points on the lines between the center and the 2 circles for my "width" angle (the angle is fixed) ;
Distort the image so the corners stick to my intersection points ;
Rotate around the center point and put it in the output image.
For the moment, I manage well to do this :
Getting the ROI ;
Scaling it with cvResize ;
Getting the intersection points shouldn't be too complicated, as it is pure geometry and I implemented it yet for another purpose.
But, I have no idea at all of how to distort the resulting image of my ROI, and I don't know if it is even possible in OpenCV. Would I have to use a kind of perspective correction ?
And, I've been trying the few good posts solutions I found by here to rotate with the rotated bounding box, but with no good results for the moment.
EDIT :
Well, I managed to do the first part of the work :
Getting a ROI in a basis image ;
Rotating and placing it at a fixed distance from the center.
I used the method explained and coded in this post : https://stackoverflow.com/a/16285286/1060921
I only added a variable to set the rotation point and get my inner circle.
NB : I set the ROI BEFORE to call the method, so the ROI in the post method is... the image size. Then I place it at the center of my final image with a cvAdd.
Here I get one pixel slices of my camera input. What I want to do now is to distort bigger slices, for example from 2 pixels on the inner circle to 5 pixels on the outer one.
See this tutorial which uses warpPerspective to correct perspective distortion.
EDIT: In your case warpAffine should be better and simpler solution.
So, you could do something like this, just use four points instead of three:
Point2f srcTri[3];
Point2f dstTri[3];
Mat rot_mat( 2, 3, CV_32FC1 );
Mat warp_mat( 2, 3, CV_32FC1 );
Mat src, warp_dst, warp_rotate_dst;
/// Load the image
src = imread( ... );
/// Set the dst image the same type and size as src
warp_dst = Mat::zeros( src.rows, src.cols, src.type() );
/// Set your 3 points to calculate the Affine Transform
srcTri[0] = Point2f( 0,0 );
srcTri[1] = Point2f( src.cols - 1, 0 );
srcTri[2] = Point2f( 0, src.rows - 1 );
dstTri[0] = Point2f( src.cols*0.0, src.rows*0.33 );
dstTri[1] = Point2f( src.cols*0.85, src.rows*0.25 );
dstTri[2] = Point2f( src.cols*0.15, src.rows*0.7 );
/// Get the Affine Transform
warp_mat = getAffineTransform( srcTri, dstTri );
/// Apply the Affine Transform just found to the src image
warpAffine( src, warp_dst, warp_mat, warp_dst.size() );
The problem is solved....I used cvGet2D,below is the sample code
CvScalar s;
s=cvGet2D(src_Image,pixel[i].x,pixel[i].y);
cvSet2D(dst_Image,pixel[i].x,pixel[i].y,s);
Where src_Iamge and dst_Image is the source and destination image correspondingly and pixel[i] is the selected pixel i wanted to draw in the dst image. I have include the real out image below.
have an source Ipl image, I want to copy some of the part of the image to a new destination image pixel by pixel. can any body tell me how can do it? I use c,c++ in opencv. For example if the below image is source image,
The real output image
EDIT:
I can see the comments suggesting cvGet2d. I think, if you just want to show "points", it is best to show them with a small neighbourhood so they can be seen where they are. For that you can draw white filled circles with origins at (x,y), on a mask, then you do the copyTo.
using namespace cv;
Mat m(input_iplimage);
Mat mask=Mat::zeros(m.size(), CV_8UC1);
p1 = Point(x,y);
r = 3;
circle(mask,p1,r, 1); // draws the circle around your point.
floodFill(mask, p1, 1); // fills the circle.
//p2, p3, ...
Mat output = Mat::zeros(m.size(),m.type()); // output starts with a black background.
m.copyTo(output, mask); // copies the selected parts of m to output
OLD post:
Create a mask and copy those pixels:
#include<opencv2/opencv.hpp>
using namespace cv;
Mat m(input_iplimage);
Mat mask=Mat::zeros(m.size(), CV_8UC1); // set mask 1 for every pixel you wanna copy.
Rect roi=Rect(x,y,width,height); // create a rectangle
mask(roi) = 1; // set it to 0.
roi = Rect(x2,y2,w2,h2);
mask(roi)=1; // set the second rectangular area for copying...
Mat output = 100*Mat::ones(m.size(),m.type()); // output with a gray background.
m.copyTo(output, mask); // copy selected areas of m to output
Alternatively you can copy Rect-by-Rect:
Mat m(input_iplimage);
Mat output = 100*Mat::ones(m.size(),m.type()); // output with a gray background.
Rect roi=Rect(x,y,width,height);
Mat m_temp, out_temp;
m_temp=m(roi);
out_temp = output(roi);
m_temp.copyTo(out_temp);
roi=Rect(x2,y2,w2,h2);
Mat m_temp, out_temp;
m_temp=m(roi);
out_temp = output(roi);
m_temp.copyTo(out_temp);
The answer to your question only requires to have look at the OpenCV documentation or just to search in your favourite search engine.
Here you've an answer for Ipl images and for newer Mat data.
For having an output as I see in your images, I'd do it setting ROI's, it's more efficient.