用户,
我想在图像上裁剪三角形并使用opencv c ++在另一个窗口中显示它。我知道所有三个坐标。 谁能帮我?我没有在互联网上找到任何关于“三角裁剪”的答案。谢谢!
编辑:这里的问题是我无法使用ROI裁剪三角形。我必须复制没有任何背景或周围的三角形。是否可以通过了解三角形的坐标[p1(302,179),p2(329,178),p3(315,205)]来创建自己的投资回报率?答案 0 :(得分:4)
cv::Mat inputImage = cv::imread("input.png");
if (inputImage.channels() > 1)
{
cv::cvtColor(inputImage, inputImage, CV_RGB2GRAY);
}
// replace these values with your actual coordinates
// I found these by first saving your provided image, then
// using Microsoft Paint
int x0 = 242;
int y0 = 164;
int x1 = 314;
int y1 = 38;
int x2 = 387;
int y2 = 164;
// then create a line masking using these three points
cv::Mat lineMask = cv::Mat::zeros(inputImage.size(), inputImage.type());
cv::line(lineMask, cv::Point(x0, y0), cv::Point(x1, y1), cv::Scalar(255, 255, 0), 1, 8, 0);
cv::line(lineMask, cv::Point(x0, y0), cv::Point(x2, y2), cv::Scalar(255, 255, 0), 1, 8, 0);
cv::line(lineMask, cv::Point(x1, y1), cv::Point(x2, y2), cv::Scalar(255, 255, 0), 1, 8, 0);
// perform contour detection on your line mask
cv::vector<cv::vector<cv::Point>> contours;
cv::vector<cv::Vec4i> hierarchy;
cv::findContours(lineMask, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
// calculate the distance to the contour
cv::Mat raw_dist(lineMask.size(), CV_32FC1);
for (int i = 0; i < lineMask.rows; i++)
{
for (int j = 0; j < lineMask.cols; j++)
{
raw_dist.at<float>(i, j) = cv::pointPolygonTest(contours[0], cv::Point2f(j, i), true);
}
}
double minVal; double maxVal;
cv::minMaxLoc(raw_dist, &minVal, &maxVal, 0, 0, cv::Mat());
minVal = std::abs(minVal);
maxVal = std::abs(maxVal);
// depicting the distances graphically
cv::Mat mask = cv::Mat::zeros(inputImage.size(), CV_8UC1);
for (int i = 0; i < mask.rows; i++)
{
for (int j = 0; j < mask.cols; j++)
{
if (raw_dist.at<float>(i, j) < 0)
{
mask.at<uchar>(i, j) = static_cast<uchar>(0);
continue;
}
mask.at<uchar>(i, j) = static_cast<uchar>(255);
}
}
// inverse the input image
cv::Mat invInput;
cv::bitwise_not(inputImage, invInput);
// then get only the region of your triangle
cv::Mat outputImage;
invInput.copyTo(outputImage, mask);
cv::bitwise_not(outputImage, outputImage);
// display for debugging purpose
cv::imshow("inputImage", inputImage);
cv::imshow("lineMask", lineMask);
cv::imshow("mask", mask);
cv::imshow("outputImage", outputImage);
cv::waitKey();
这是您的inputImage
:
这是您的lineMask
:
这是您创建的二进制文件mask
:
这是你的最终outputImage
:
参考文献:
答案 1 :(得分:3)
您可以使用掩码执行此操作,如下面的代码所示
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main( int, char** argv )
{
Mat src = imread( argv[1] );
Mat gray;
cvtColor(src, gray, COLOR_BGR2GRAY );
gray = gray < 127;
vector<vector<Point> > contours;
findContours(gray, contours,
RETR_EXTERNAL,
CHAIN_APPROX_SIMPLE);
for( size_t i = 0; i< contours.size(); i++ )
{
Rect rect = boundingRect(contours[i]);
Mat mask = gray(rect);
Mat srcROI = src(rect);
srcROI.setTo(Scalar(0,0,255),mask);
imshow("srcROI",srcROI);
waitKey();
}
imshow( "result", src );
waitKey(0);
return(0);
}
编辑:根据问题的变化我建议下面的测试代码
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
int main( int, char** argv )
{
Mat src = imread("lena.jpg");
vector<Point> points;
points.push_back( Point(200,200));
points.push_back( Point(370,370));
points.push_back( Point(220,410));
Mat mask = Mat::zeros( src.size(), CV_8UC1 );
fillConvexPoly( mask, points, Scalar( 255 ));
Rect rect = boundingRect( points );
Mat roi = src( rect ).clone();
mask = mask( rect ).clone();
rect.x = rect.x - 180;
rect.y = rect.y - 180;
Mat srcROI = src( rect );
roi.copyTo( srcROI, mask );
imshow( "result", src );
waitKey(0);
return(0);
}
答案 2 :(得分:3)
正如您所说,您知道三角形的坐标,使用下面的代码可以找到三角形。
Mat image = imread("imagePath");
bitwise_not(image, image);
Mat grayImage;
cv::cvtColor(image, grayImage, CV_RGB2GRAY);
cv::vector<cv::vector<cv::Point> > contours;
cv::vector<cv::Vec4i> hierarchy;
cv::findContours(grayImage, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
Mat contourMat(grayImage.size(), grayImage.type(), Scalar(255));
for(int i = 0; i < contours.size(); i++)
{
if(contours[i].data()->x == 314 && contours[i].data()->y == 37)
drawContours(contourMat, contours, i, Scalar(0), CV_FILLED, 8, hierarchy);
}
imshow("WindowName", contourMat);
希望这会有所帮助。