Crop image in diagonal square - c++

I have the following image in a Mat:
The black rectangle is created using the class rotatedRect. How can I have the following result?
EDIT:
I manage to do it with the following code:
cv::Mat src, dst; float angle, x, y;
cv::Mat imgRotated = cv::getRotationMatrix2D(Point(50,50), angle,
1.0); cv::warpAffine(src, dst, imgRotated, Size(x,y));
imshow("image", dst);

You can use cv::warpAffine() together with cv::getRotationMatrix2D().
There is an example here.

Related

OpenCV cv::Circle comes out gray on iPhone UI

Currently I am using OpenCV to process images from an AVCaptureSession. The app right now takes these images and draws cv::Circles on the blobs. The tracking is working but when I draw the circle, it comes out as this gray, distorted circle when it should be green. Is it that OpenCV drawing functions don't work properly with iOS apps? Or is there something I can do to fix it?
Any help would be appreciated.
Here is a screen shot: (Ignore that giant green circle on the bottom)
The cv::Circle is around the outside of the black circle.
Here is where I converted the CMSampleBuffer into a cv::Mat:
enter code here CVImageBufferRef pixelBuff = CMSampleBufferGetImageBuffer(sampleBuffer);
cv::Mat cvMat;
CVPixelBufferLockBaseAddress(pixelBuff, 0);
int bufferWidth = CVPixelBufferGetWidth(pixelBuff);
int bufferHeight = CVPixelBufferGetHeight(pixelBuff);
unsigned char *pixel = (unsigned char *)CVPixelBufferGetBaseAddress(pixelBuff);
cvMat = cv::Mat(bufferHeight, bufferWidth, CV_8UC4, pixel);
cv::Mat grayMat;
cv::cvtColor(cvMat, grayMat, CV_BGR2GRAY);
CVPixelBufferUnlockBaseAddress(pixelBuff, 0);
This is the cv::Circle command:
if (keypoints.size() > 0) {
cv::Point p(keypoints[0].pt.x, keypoints[0].pt.y);
printf("x: %f, y: %f\n",keypoints[0].pt.x, keypoints[0].pt.y);
cv::circle(cvMat, p, keypoints[0].size/2, cv::Scalar(0,255,0), 2, 8, 0);
}
Keypoints is the vector of blobs that have been detected.

Remove black Background from an image.

I'm new to image processing and development. I have used opencv, There I need to extract circle from a given image. That circle given x, y coordinates are (radius) in Oder to do that I used following code. But my problem is I have to take black rectangle. So the image patch having unwanted black pixels. How do I save just only circle?
my code
double save_key_points(Mat3b img, double x, double y, double radius, string
filename, string foldername)
{
// print image height and width first and check.
Vec3f circ(x, y, radius);
// Draw the mask: white circle on black background
Mat1b mask(img.size(), uchar(0));
circle(mask, Point(circ[0], circ[1]), circ[2], Scalar(255), CV_FILLED);
// Compute the bounding box
Rect bbox(circ[0] - circ[2], circ[1] - circ[2], 2 * circ[2], 2 * circ[2]);
// Create a black image
Mat3b res(img.size(), Vec3b(0, 0, 0));
// Copy only the image under the white circle to black image
img.copyTo(res, mask);
// Crop according to the roi
res = res(bbox);
//remove black but doesn't work.
Mat tmp, alpha;
threshold(res, alpha, 100, 255, THRESH_BINARY);
// Save the image
string path = "C:\\Users\\bb\\Desktop\\test_results\\test_case8\\" + foldername + filename + ".png";
imwrite(path, res);
Mat keypointimg = imread(path, CV_LOAD_IMAGE_GRAYSCALE);
//print the cordinate of one patch.
cordinate_print(keypointimg, radius);
}
(Here i want without black background)
If I understand what you are asking correctly you could remove the black from an image you can use a mask. The mask can highlight anything that is of a certain colour or in your case the shade of black. Check out the link for this implementation and see if it is what you are looknig for. It is in python but can be easily adapted.
Image Filtering

how to implement Imrotate of Matlab in Opencv?

for rotation in Opencv, i used following code:
Mat rotate(Mat src, double angle)
{
Mat dst;
Point2f pt(src.cols/2., src.rows/2.);
Mat r = getRotationMatrix2D(pt, angle, 1.0);
warpAffine(src, dst, r, Size(src.cols, src.rows));
return dst;
}
and in matlab i used:
im = imrotate(img, angle, 'bilinear', 'crop');
but results not equivalent.
how to fix that or implement imrotate of matlab in c++?
i got this code around 1 year ago. I do not remember where i got this. So i do not take any credit of this code. But i modified this code little.
The result is not exactly match with matlab result. But it is good enough to use.
cv::Mat imRotate(const cv::Mat source, double angle) {
cv::Mat dst;
// Special Cases
if (std::fmod(angle, 360.0) == 0.0)
dst = source;
else{
cv::Point2f center(source.cols / 2.0F, source.rows / 2.0F);
cv::Mat rot = cv::getRotationMatrix2D(center, angle, 1.0);
// determine bounding rectangle
cv::Rect bbox = cv::RotatedRect(center, source.size(), angle).boundingRect();
// adjust transformation matrix
rot.at<double>(0, 2) += bbox.width / 2.0 - center.x;
rot.at<double>(1, 2) += bbox.height / 2.0 - center.y;
cv::warpAffine(source, dst, rot, bbox.size(), cv::INTER_LINEAR);
}
return dst;
}

How to maintain white background when using opencv warpaffine

I'm trying to rotate image using
void rotate(cv::Mat& src, double angle, cv::Mat& dst)
{
int len = std::max(src.cols, src.rows);
cv::Point2f pt(len / 2., len / 2.);
cv::Mat r = cv::getRotationMatrix2D(pt, angle, 1.0);
cv::warpAffine(src, dst, r, cv::Size(src.cols, src.rows));
}
by giving angle, source and destination image. Rotation works correctly as follows.
I want to make black areas white. I have tried with
cv::Mat dst = cv::Mat::ones(src.cols, src.rows, src.type());
before calling rotate, but no change in result. How can I achieve this?
Note: I am looking for solution which achieve this while doing the rotation. obviously by making black areas white after the rotation this can be achieved.
You will want to use the borderMode and borderValue arguments of the warpAffine function to accomlish this. By setting the mode to BORDER_CONSTANT it will use a constant value for border pixels (i.e. outside the image), and you can set the value to the constant value you want to use (i.e. white). It would look something like:
cv::warpAffine(src, dst, r,
cv::Size(src.cols, src.rows),
cv::INTER_LINEAR,
cv::BORDER_CONSTANT,
cv::Scalar(255, 255, 255));
For more details see the OpenCV API Documentation.

How to create a semi transparent shape?

I would like to know how to draw semi-transparent shapes in OpenCV, similar to those in the image below (from http://tellthattomycamera.wordpress.com/)
I don't need those fancy circles, but I would like to be able to draw a rectangle, e.g, on a 3 channel color image and specify the transparency of the rectangle, something like
rectangle (img, Point (100,100), Point (300,300), Scalar (0,125,125,0.4), CV_FILLED);
where 0,125,125 is the color of the rectangle and 0.4 specifies the transparency.
However OpenCV doesn't have this functionality built into its drawing functions. How can I draw shapes in OpenCV so that the original image being drawn on is partially visible through the shape?
The image below illustrates transparency using OpenCV. You need to do an alpha blend between the image and the rectangle. Below is the code for one way to do this.
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
int main( int argc, char** argv )
{
cv::Mat image = cv::imread("IMG_2083s.png");
cv::Mat roi = image(cv::Rect(100, 100, 300, 300));
cv::Mat color(roi.size(), CV_8UC3, cv::Scalar(0, 125, 125));
double alpha = 0.3;
cv::addWeighted(color, alpha, roi, 1.0 - alpha , 0.0, roi);
cv::imshow("image",image);
cv::waitKey(0);
}
In OpenCV 3 this code worked for me:
cv::Mat source = cv::imread("IMG_2083s.png");
cv::Mat overlay;
double alpha = 0.3;
// copy the source image to an overlay
source.copyTo(overlay);
// draw a filled, yellow rectangle on the overlay copy
cv::rectangle(overlay, cv::Rect(100, 100, 300, 300), cv::Scalar(0, 125, 125), -1);
// blend the overlay with the source image
cv::addWeighted(overlay, alpha, source, 1 - alpha, 0, source);
Source/Inspired by: http://bistr-o-mathik.org/2012/06/13/simple-transparency-in-opencv/
Adding to Alexander Taubenkorb's answer, you can draw random (semi-transparent) shapes by replacing the cv::rectangle line with the shape you want to draw.
For example, if you want to draw a series of semi-transparent circles, you can do it as follows:
cv::Mat source = cv::imread("IMG_2083s.png"); // loading the source image
cv::Mat overlay; // declaring overlay matrix, we'll copy source image to this matrix
double alpha = 0.3; // defining opacity value, 0 means fully transparent, 1 means fully opaque
source.copyTo(overlay); // copying the source image to overlay matrix, we'll be drawing shapes on overlay matrix and we'll blend it with original image
// change this section to draw the shapes you want to draw
vector<Point>::const_iterator points_it; // declaring points iterator
for( points_it = circles.begin(); points_it != circles.end(); ++points_it ) // circles is a vector of points, containing center of each circle
circle(overlay, *points_it, 1, (0, 255, 255), -1); // drawing circles on overlay image
cv::addWeighted(overlay, alpha, source, 1 - alpha, 0, source); // blending the overlay (with alpha opacity) with the source image (with 1-alpha opacity)
For C++, I personally like the readability of overloaded operators for scalar multiplication and matrix addition:
... same initial lines as other answers above ...
// blend the overlay with the source image
source = source * (1.0 - alpha) + overlay * alpha;