我愿意从扭曲的图像中得到一个简单的矩形。
例如,一旦我有这种图像:
...我想裁剪下面矩形对应的区域:
...但我的代码正在提取这个更大的框架:
我的代码如下:
int main(int argc, char** argv) {
cv::Mat img = cv::imread(argv[1]);
// Convert RGB Mat to GRAY
cv::Mat gray;
cv::cvtColor(img, gray, CV_BGR2GRAY);
// Store the set of points in the image before assembling the bounding box
std::vector<cv::Point> points;
cv::Mat_<uchar>::iterator it = gray.begin<uchar>();
cv::Mat_<uchar>::iterator end = gray.end<uchar>();
for (; it != end; ++it) {
if (*it)
points.push_back(it.pos());
}
// Compute minimal bounding box
Rect box = cv::boundingRect(cv::Mat(points));
// Draw bounding box in the original image (debug purposes)
cv::Point2f vertices[4];
vertices[0] = Point2f(box.x, box.y +box.height);
vertices[1] = Point2f(box.x, box.y);
vertices[2] = Point2f(box.x+ box.width, box.y);
vertices[3] = Point2f(box.x+ box.width, box.y +box.height);
for (int i = 0; i < 4; ++i) {
cv::line(img, vertices[i], vertices[(i + 1) % 4], cv::Scalar(0, 255, 0), 1, CV_AA);
cout << "==== vertices (x, y) = " << vertices[i].x << ", " << vertices[i].y << endl;
}
cv::imshow("box", img);
cv::imwrite("box.png", img);
waitKey(0);
return 0;
}
有关如何找到菱形边角并尝试将它们缩小为较小矩形的任何想法吗?
答案 0 :(得分:2)
这个问题最困难的部分实际上是找到菱形角的位置。如果实际使用中的图像与您的示例有很大不同,则查找菱形边角的此特定过程可能无效。一旦达到此目的,您可以根据它们与图像中心的距离对角点进行排序。您正在寻找最接近图像中心的点。
首先,您必须为排序比较定义一个仿函数(如果您可以使用C ++ 11,这可能是一个lambda):
struct CenterDistance
{
CenterDistance(cv::Point2f pt) : center(pt){}
template <typename T> bool operator() (cv::Point_<T> p1, cv::Point_<T> p2) const
{
return cv::norm(p1-center) < cv::norm(p2-center);
}
cv::Point2f center;
};
这实际上不需要是模板operator()
,但它可以适用于任何cv::Point_
类型。
对于您的示例图像,图像角定义非常明确,因此您可以像FAST一样使用角点检测器。然后,您可以使用cv::convexHull()
来获取外部点,这些点应该只是菱形角。
int main(int argc, char** argv) {
cv::Mat img = cv::imread(argv[1]);
// Convert RGB Mat to GRAY
cv::Mat gray;
cv::cvtColor(img, gray, CV_BGR2GRAY);
// Detect image corners
std::vector<cv::KeyPoint> kpts;
cv::FAST(gray, kpts, 50);
std::vector<cv::Point2f> points;
cv::KeyPoint::convert(kpts, points);
cv::convexHull(points, points);
cv::Point2f center(img.size().width / 2.f, img.size().height / 2.f);
CenterDistance centerDistance(center);
std::sort(points.begin(), points.end(), centerDistance);
//The two points with minimum distance are what we want
cv::rectangle(img, points[0], points[1], cv::Scalar(0,255,0));
cv::imshow("box", img);
cv::imwrite("box.png", img);
cv::waitKey(0);
return 0;
}
请注意,您可以使用cv::rectangle()
而不是从行构建绘制的矩形。结果是: