从带有彩色圆圈作为标记的图像开始,例如:
请注意,这是一个 png 图像,即采用无损压缩,保留了实际颜色。如果您使用像 jpeg 这样的有损压缩,颜色会稍微改变,并且您无法像此处那样通过精确匹配对它们进行分段。
您需要找到每个标记的中心。
- 使用分割(已知)颜色inRange http://docs.opencv.org/2.4/modules/core/doc/operations_on_arrays.html?#cv.InRange
- 查找具有给定颜色的所有连接组件,其中查找轮廓 http://docs.opencv.org/2.4/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?s#findcontours
- 找到最大的斑点,这里完成了最大元素 http://www.cplusplus.com/reference/algorithm/max_element/带有 lambda 函数,并且distance http://www.cplusplus.com/reference/iterator/distance/?kw=distance。您可以为此使用 for 循环。
- 找到最大斑点的质心,这里完成了moments http://docs.opencv.org/2.4/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?s#moments。最终,您也可以在这里使用循环。
- 将中心添加到您的source顶点。
Your 目的地顶点只是目标图像的四个角。
然后你可以使用获取透视变换 http://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html?#getperspectivetransform and 扭曲透视 http://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html?#warpperspective查找并应用扭曲。
结果图像是:
Code:
#include <opencv2/opencv.hpp>
#include <vector>
#include <algorithm>
using namespace std;
using namespace cv;
int main()
{
// Load image
Mat3b img = imread("path_to_image");
// Create a black output image
Mat3b out(300,300,Vec3b(0,0,0));
// The color of your markers, in order
vector<Scalar> colors{ Scalar(0, 0, 255), Scalar(0, 255, 0), Scalar(255, 0, 0), Scalar(0, 255, 255) }; // red, green, blue, yellow
vector<Point2f> src_vertices(colors.size());
vector<Point2f> dst_vertices = { Point2f(0, 0), Point2f(0, out.rows - 1), Point2f(out.cols - 1, out.rows - 1), Point2f(out.cols - 1, 0) };
for (int idx_color = 0; idx_color < colors.size(); ++idx_color)
{
// Detect color
Mat1b mask;
inRange(img, colors[idx_color], colors[idx_color], mask);
// Find connected components
vector<vector<Point>> contours;
findContours(mask, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
// Find largest
int idx_largest = distance(contours.begin(), max_element(contours.begin(), contours.end(), [](const vector<Point>& lhs, const vector<Point>& rhs) {
return lhs.size() < rhs.size();
}));
// Find centroid of largest component
Moments m = moments(contours[idx_largest]);
Point2f center(m.m10 / m.m00, m.m01 / m.m00);
// Found marker center, add to source vertices
src_vertices[idx_color] = center;
}
// Find transformation
Mat M = getPerspectiveTransform(src_vertices, dst_vertices);
// Apply transformation
warpPerspective(img, out, M, out.size());
imshow("Image", img);
imshow("Warped", out);
waitKey();
return 0;
}