copying non-rectangular roi opencv
First create a mask image using your four co-ordinates.
Now using Mat::copyTo() copy your balck image to source here you can use above mask.
Allocate black image and mask as source size
Mat src=imread("img.png",1);
Mat black(src.rows, src.cols, src.type(), cv::Scalar::all(0));
Mat mask(src.rows, src.cols, CV_8UC1, cv::Scalar(0));
Now create mask image using drawContours, here you should use CV_FILLED for contour thickness.
Like
vector< vector<Point> > co_ordinates;
co_ordinates.push_back(vector<Point>());
co_ordinates[0].push_back(P1);
co_ordinates[0].push_back(P2);
co_ordinates[0].push_back(P3);
co_ordinates[0].push_back(P4);
drawContours( mask,co_ordinates,0, Scalar(255),CV_FILLED, 8 );
Finally copy black image to source using above mask
black.copyTo(src,mask);
See below result,
Edit :
Based on your comment below here is the steps you need to follow
First create Mask image as described above
Copy the the source image to new Mat dst1 using the mask.
Invert your mask and copy destination image to a new Mat dst2
For final result just add up dest1 and dest2 to new Mat.
Suppose you already created mask as above
Copy source to new Mat
Mat dst1;
src.copyTo(dst1,mask);
Now invert Mask and copy destination image to new Mat
Mat dst2;
bitwise_not(mask,mask);
dst.copyTo(dst2,mask);
Get final result by adding both
Mat result=dest1+dest2;
In case your both image are of different size then you can use following code
Here you should use image ROI for copy, create mask etc..
![Mat src=imread("src.png",1);
Mat dst=imread("dest.jpg",1);
int new_w=0;
int new_h=0;
if(src.cols>dst.cols)
new_w=dst.cols;
else
new_w=src.cols;
if(src.rows>dst.rows)
new_h=dst.rows;
else
new_h=src.rows;
Rect rectROI(0,0,new_w,new_h);
Mat mask(new_h, new_w, CV_8UC1, cv::Scalar(0));
Point P1(107,41);
Point P2(507,61);
Point P3(495,280);
Point P4(110,253);
vector< vector<Point> > co_ordinates;
co_ordinates.push_back(vector<Point>());
co_ordinates\[0\].push_back(P1);
co_ordinates\[0\].push_back(P2);
co_ordinates\[0\].push_back(P3);
co_ordinates\[0\].push_back(P4);
drawContours( mask,co_ordinates,0, Scalar(255),CV_FILLED, 8 );
Mat srcROI=src(rectROI);
Mat dstROI=dst(rectROI);
Mat dst1;
Mat dst2;
srcROI.copyTo(dst1,mask);
imwrite("dst1.jpg",dst1);
bitwise_not(mask,mask);
dstROI.copyTo(dst2,mask);
dstROI.setTo(0);
dstROI=dst1+dst2;
imshow("final result",dst);][4]
What's the most efficient way to select a non-rectangular ROI of an Image in OpenCV?
Draw the mask with fillPoly
:
mask = np.ones((1000, 2000)) # (height, width)
myROI = [(750, 0), (900, 1000), (1000, 1000), (1500, 0)] # (x, y)
cv2.fillPoly(mask, [np.array(myROI)], 0)
This should take ~1ms.
opencv how to visualize a non-rectangular region (roi) in a performant way
Is your mask of constant colour? Assuming mask is the same dimension as the image(you can easily scale it) :-
//Manually instead of addWeighted()
for (uint ri = 0; ri < 480; ++ri)
for (uint ci = 0; ci < 640; ++ci)
{
if (mask[ri * 640 + ci])
{
image.at<uchar>(ri,ci) [0] = image.at<uchar>(ri,ci) [0] * weight_blue;
image.at<uchar>(ri,ci) [1] = image.at<uchar>(ri,ci) [1] * weight_green;
image.at<uchar>(ri,ci) [2] = image.at<uchar>(ri,ci) [2] * weight_red;
}
}
NumPy/OpenCV 2: how do I crop non-rectangular region?
*edit - updated to work with images that have an alpha channel.
This worked for me:
- Make a mask with all black (all masked)
- Fill a polygon with white in the shape of your ROI
- combine the mask and your image to get the ROI with black everywhere else
You probably just want to keep the image and mask separate for functions that accept masks. However, I believe this does what you specifically asked for:
import cv2
import numpy as np
# original image
# -1 loads as-is so if it will be 3 or 4 channel as the original
image = cv2.imread('image.png', -1)
# mask defaulting to black for 3-channel and transparent for 4-channel
# (of course replace corners with yours)
mask = np.zeros(image.shape, dtype=np.uint8)
roi_corners = np.array([[(10,10), (300,300), (10,300)]], dtype=np.int32)
# fill the ROI so it doesn't get wiped out when the mask is applied
channel_count = image.shape[2] # i.e. 3 or 4 depending on your image
ignore_mask_color = (255,)*channel_count
cv2.fillPoly(mask, roi_corners, ignore_mask_color)
# from Masterfool: use cv2.fillConvexPoly if you know it's convex
# apply the mask
masked_image = cv2.bitwise_and(image, mask)
# save the result
cv2.imwrite('image_masked.png', masked_image)
OpenCV ROI Out-of-bounds: Fill with black?
I found that the best way to do this was to get the section of the ROI that was within bounds, then calculate how much on each side (top/bottom/left/right) of the ROI was out of bounds, then use the copyMakeBorder
function to pad that much black border around each side. It worked out very well. It looks something like this now:
Mat getPaddedROI(const Mat &input, int top_left_x, int top_left_y, int width, int height, Scalar paddingColor) {
int bottom_right_x = top_left_x + width;
int bottom_right_y = top_left_y + height;
Mat output;
if (top_left_x < 0 || top_left_y < 0 || bottom_right_x > input.cols || bottom_right_y > input.rows) {
// border padding will be required
int border_left = 0, border_right = 0, border_top = 0, border_bottom = 0;
if (top_left_x < 0) {
width = width + top_left_x;
border_left = -1 * top_left_x;
top_left_x = 0;
}
if (top_left_y < 0) {
height = height + top_left_y;
border_top = -1 * top_left_y;
top_left_y = 0;
}
if (bottom_right_x > input.cols) {
width = width - (bottom_right_x - input.cols);
border_right = bottom_right_x - input.cols;
}
if (bottom_right_y > input.rows) {
height = height - (bottom_right_y - input.rows);
border_bottom = bottom_right_y - input.rows;
}
Rect R(top_left_x, top_left_y, width, height);
copyMakeBorder(input(R), output, border_top, border_bottom, border_left, border_right, BORDER_CONSTANT, paddingColor);
}
else {
// no border padding required
Rect R(top_left_x, top_left_y, width, height);
output = input(R);
}
return output;
}
And you can easily make the padding whatever colour you like, which is nice.
OpenCV - Cropping non rectangular region from image using C++
The procedure for cropping an arbitrary quadrilateral (or any polygon for that matter) part of an image is summed us as:
- Generate a "mask". The mask is black where you want to keep the image, and white where you don't want to keep it
- Compute the "bitwise_and" between your input image and the mask
So, lets assume you have an image. Throughout this I'll use an image size of 30x30 for simplicity, you can change this to suit your use case.
cv::Mat source_image = cv::imread("filename.txt");
And you have four points you want to use as the corners:
cv::Point corners[1][4];
corners[0][0] = Point( 10, 10 );
corners[0][1] = Point( 20, 20 );
corners[0][2] = Point( 30, 10 );
corners[0][3] = Point( 20, 10 );
const Point* corner_list[1] = { corners[0] };
You can use the function cv::fillPoly
to draw this shape on a mask:
int num_points = 4;
int num_polygons = 1;
int line_type = 8;
cv::Mat mask(30,30,CV_8UC3, cv::Scalar(0,0,0));
cv::fillPoly( mask, corner_list, &num_points, num_polygons, cv::Scalar( 255, 255, 255 ), line_type);
Then simply compute the bitwise_and of the image and mask:
cv::Mat result;
cv::bitwise_and(source_image, mask, result);
result
now has the cropped image in it. If you want the edges to end up white instead of black you could instead do:
cv::Mat result_white(30,30,CV_8UC3, cv::Scalar(255,255,255));
cv::bitwise_and(source_image, mask, result_white, mask);
In this case we use bitwise_and
's mask parameter to only do the bitwise_and inside the mask. See this tutorial for more information and links to all the functions I mentioned.
Related Topics
"Volatile" Qualifier and Compiler Reorderings
Get Private Data Members for Non Intrusive Boost Serialization C++
How Concatenate a String and a Const Char
Specifying Default Parameter When Calling C++ Function
Trying to Pass String Literals as Template Arguments
C++ 128/256-Bit Fixed Size Integer Types
Good C++ Solutions to the "Bring All the Zeros to the Back of the Array" Interview Challenge
Drawing in a Win32 Console on C++
Unit Test That a Class Is Non Copyable, and Other Compile-Time Properties
How to Determine the Value of Socket Listen() Backlog Parameter
Understanding Virtual Base Classes and Constructor Calls
How to Determine If Returned Pointer Is on the Stack or Heap
Difference Between Console (/Subsystem:Console) and Windows (/Subsystem:Windows)
Inconsistent Use of Const Qualifier Between Declaration and Definition