- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章OpenCV和C++实现图像的翻转(镜像)、平移、旋转、仿射与透视变换由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
官网教程 。
。
头文件 quick_opencv.h:声明类与公共函数 。
#pragma once#include <opencv2opencv.hpp>using namespace cv;class QuickDemo {public: ... void flip_Demo(Mat& image); void rotate_Demo(Mat& image); void move_Demo(Mat& image); void Affine_Demo(Mat& image); void toushi_Demo(Mat& image); void perspective_detect(Mat& image);};
主函数调用该类的公共成员函数 。
#include <opencv2opencv.hpp>#include <quick_opencv.h>#include <iostream>using namespace cv;int main(int argc, char** argv) { Mat src = imread("D:\Desktop\pandas.jpg"); if (src.empty()) { printf("Could not load images..."); return -1; } namedWindow("input", WINDOW_NORMAL); imshow("input", src); QuickDemo qk; ... qk.Affine_Demo(src); qk.move_Demo(src); qk.flip_Demo(src); qk.toushi_Demo(src); qk.perspective_detect(src); waitKey(0); destroyAllWindows(); return 0;}
源文件 quick_demo.cpp:实现类与公共函数 。
void QuickDemo::flip_Demo(Mat& image) { Mat dst0, dst1, dst2; flip(image, dst0, 0); flip(image, dst1, 1); flip(image, dst2, -1); imshow("dst0_上下翻转", dst0); imshow("dst1_左右翻转", dst1); imshow("dst2_对角线翻转", dst2); //旋转180度}
。
二维图像一般情况下的变换矩阵(旋转+平移),当我们只需要平移的时候,取 θ 的值为0,a和b的值就代表了图像沿x轴和y轴移动的距离;其中原图 (原图大小,不执行缩放) 。
变换矩阵计算:
其中:
Mat getRotationMatrix2D( Point2f center, 源图像中旋转的中心 double angle, 角度以度为单位的旋转角度。正值表示逆时针旋转(坐标原点假定为左上角)。 double scale 各向同性比例因子。 ) 。
函数签名 。
void warpAffine( InputArray src, 输入矩阵 OutputArray dst, 输出矩阵 InputArray M, 2×3 变换矩阵 Size dsize, 输出图像大小 int flags = INTER_LINEAR, 插值方式:默认线性插值 int borderMode = BORDER_CONSTANT, 边缘处理方式 const Scalar& borderValue = Scalar() 边缘填充值,默认=0 ),
保留所有原图像素的旋转,原理:
void QuickDemo::rotate_Demo(Mat& image) { Mat dst_0, dst_1, M; int h = image.rows; int w = image.cols; M = getRotationMatrix2D(Point(w / 2, h / 2), 45, 1.0); warpAffine(image, dst_0, M, image.size()); double cos = abs(M.at<double>(0, 0)); double sin = abs(M.at<double>(0, 1)); int new_w = cos * w + sin * h; int new_h = cos * h + sin * w; M.at<double>(0, 2) += (new_w / 2.0 - w / 2); M.at<double>(1, 2) += (new_h / 2.0 - h / 2); warpAffine(image, dst_1, M, Size(new_w, new_h), INTER_LINEAR, 0, Scalar(255, 255, 0)); imshow("旋转演示0", dst_0); imshow("旋转演示1", dst_1);}
依次为:原图,旋转45度,保留所有原图像素的旋转45度 。
void QuickDemo::move_Demo(Mat& image) { Mat dst_move; Mat move_mat = (Mat_<double>(2, 3) << 1, 0, 10, 0, 1, 30);//沿x轴移动10沿y轴移动30 warpAffine(image, dst_move, move_mat, image.size()); imshow("dst_move", dst_move); double angle_ = 3.14159265354 / 16.0; cout << "pi=" << cos(angle_) << endl; Mat rota_mat = (Mat_<double>(2, 3) << cos(angle_), -sin(angle_), 1, sin(angle_), cos(angle_), 1); warpAffine(image, rotate_dst, rota_mat, image.size()); imshow("rotate_dst", rotate_dst);}
。
Mat getAffineTransform( 返回变换矩阵 const Point2f src[], 变换前三个点的数组 const Point2f dst[] 变换后三个点的数组 ); void 。
void QuickDemo::Affine_Demo(Mat& image) { Mat warp_dst; Mat warp_mat(2, 3, CV_32FC1); Point2f srcTri[3]; Point2f dstTri[3]; /// 设置源图像和目标图像上的三组点以计算仿射变换 srcTri[0] = Point2f(0, 0); srcTri[1] = Point2f(image.cols - 1, 0); srcTri[2] = Point2f(0, image.rows - 1); for (size_t i = 0; i < 3; i++){ circle(image, srcTri[i], 2, Scalar(0, 0, 255), 5, 8); } dstTri[0] = Point2f(image.cols * 0.0, image.rows * 0.13); dstTri[1] = Point2f(image.cols * 0.95, image.rows * 0.15); dstTri[2] = Point2f(image.cols * 0.15, image.rows * 0.9); warp_mat = getAffineTransform(srcTri, dstTri); warpAffine(image, warp_dst, warp_mat, warp_dst.size()); imshow("warp_dst", warp_dst);}
。
获取透射变换的矩阵:
Mat getPerspectiveTransform( 返回变换矩阵 const Point2f src[], 透视变换前四个点的 数组 const Point2f dst[], 透视变换后四个点的 数组 int solveMethod = DECOMP_LU ) 。
透射变换 。
void warpPerspective( InputArray src, 原图像 OutputArray dst, 返回图像 InputArray M, 透视变换矩阵 Size dsize, 返回图像的大小(宽,高) int flags = INTER_LINEAR, 插值方法 int borderMode = BORDER_CONSTANT, 边界处理 const Scalar& borderValue = Scalar() 缩放处理 ) 。
void QuickDemo::toushi_Demo(Mat& image) { Mat toushi_dst, toushi_mat; Point2f toushi_before[4]; toushi_before[0] = Point2f(122, 220); toushi_before[1] = Point2f(397, 121); toushi_before[2] = Point2f(133, 339); toushi_before[3] = Point2f(397, 218); int width_0 = toushi_before[1].x - toushi_before[0].x; int height_0 = toushi_before[1].y - toushi_before[0].y; int width_1 = toushi_before[2].x - toushi_before[0].x; int height_1 = toushi_before[2].y - toushi_before[0].y; int width = (int)sqrt(width_0 * width_0 + height_0 * height_0); int height = (int)sqrt(width_1 * width_1 + height_1 * height_1); Point2f toushi_after[4]; toushi_after[0] = Point2f(2, 2); // x0, y0 toushi_after[1] = Point2f(width+2, 2); // x1, y0 toushi_after[2] = Point2f(2, height+2); // x0, y1 toushi_after[3] = Point2f(width + 2, height + 2); // x1, y1 for (size_t i = 0; i < 4; i++){ cout << toushi_after[i] << endl; } toushi_mat = getPerspectiveTransform(toushi_before, toushi_after); warpPerspective(image, toushi_dst, toushi_mat, Size(width, height)); imshow("toushi_dst", toushi_dst);}
自动化透视矫正图像
流程:
inline void Intersection(Point2i& interPoint, Vec4i& line1, Vec4i& line2) { // x1, y1, x2, y2 = line1[0], line1[1], line1[2], line1[3] int A1 = line1[3] - line1[1]; int B1 = line1[0] - line1[2]; int C1 = line1[1] * line1[2] - line1[0] * line1[3]; int A2 = line2[3] - line2[1]; int B2 = line2[0] - line2[2]; int C2 = line2[1] * line2[2] - line2[0] * line2[3]; interPoint.x = static_cast<int>((B1 * C2 - B2 * C1) / (A1 * B2 - A2 * B1)); interPoint.y = static_cast<int>((C1 * A2 - A1 * C2) / (A1 * B2 - A2 * B1));}void QuickDemo::perspective_detect(Mat& image) { Mat gray_dst, binary_dst, morph_dst; // 二值化 cvtColor(image, gray_dst, COLOR_BGR2GRAY); threshold(gray_dst, binary_dst, 0, 255, THRESH_BINARY_INV | THRESH_OTSU); //形态学操作 Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5)); morphologyEx(binary_dst, morph_dst, MORPH_CLOSE, kernel, Point(-1, -1), 3); bitwise_not(morph_dst, morph_dst); imshow("morph_dst2", morph_dst); //轮廓查找与可视化 vector<vector<Point>> contours; vector<Vec4i> hierarches; int height = image.rows; int width = image.cols; Mat contours_Img = Mat::zeros(image.size(), CV_8UC3); findContours(morph_dst, contours, hierarches, RETR_TREE, CHAIN_APPROX_SIMPLE); for (size_t i = 0; i < contours.size(); i++){ Rect rect = boundingRect(contours[i]); if (rect.width > width / 2 && rect.width < width - 5) { drawContours(contours_Img, contours, i, Scalar(0, 0, 255), 2, 8, hierarches, 0, Point()); } } imshow("contours_Img", contours_Img); vector<Vec4i> lines; Mat houghImg; int accu = min(width * 0.5, height * 0.5); cvtColor(contours_Img, houghImg, COLOR_BGR2GRAY); HoughLinesP(houghImg, lines, 1, CV_PI / 180, accu, accu*0.6, 0); Mat lineImg = Mat::zeros(image.size(), CV_8UC3); for (size_t i = 0; i < lines.size(); i++){ Vec4i ln = lines[i]; line(lineImg, Point(ln[0], ln[1]), Point(ln[2], ln[3]), Scalar(0, 0, 255), 2, 8, 0); } // 寻找与定位上下左右四条直线 int delta = 0; Vec4i topline = { 0, 0, 0, 0 }; Vec4i bottomline; Vec4i leftline, rightline; for (size_t i = 0; i < lines.size(); i++) { Vec4i ln = lines[i]; delta = abs(ln[3] - ln[1]); // y2-y1 //topline if (ln[3] < height / 2.0 && ln[1] < height / 2.0 && delta < accu - 1) { if (topline[3] > ln[3] && topline[3] > 0) { topline = lines[i]; } else { topline = lines[i]; } } if (ln[3] > height / 2.0 && ln[1] > height / 2.0 && delta < accu - 1) { bottomline = lines[i]; } if (ln[0] < width / 2.0 && ln[2] < width / 2.0) { leftline = lines[i]; } if (ln[0] > width / 2.0 && ln[2] > width / 2.0) { rightline = lines[i]; } } cout << "topline: " << topline << endl; cout << "bottomline: " << bottomline << endl; cout << "leftline: " << leftline << endl; cout << "rightline: " << rightline << endl; // 计算上述四条直线交点(两条线的交点:依次为左上,右上,左下,右下) Point2i p0, p1, p2, p3; Intersection(p0, topline, leftline); Intersection(p1, topline, rightline); Intersection(p2, bottomline, leftline); Intersection(p3, bottomline, rightline); circle(lineImg, p0, 2, Scalar(255, 0, 0), 2, 8, 0); circle(lineImg, p1, 2, Scalar(255, 0, 0), 2, 8, 0); circle(lineImg, p2, 2, Scalar(255, 0, 0), 2, 8, 0); circle(lineImg, p3, 2, Scalar(255, 0, 0), 2, 8, 0); imshow("Intersection", lineImg); //透视变换 vector<Point2f> src_point(4); src_point[0] = p0; src_point[1] = p1; src_point[2] = p2; src_point[3] = p3; int new_height = max(abs(p2.y - p0.y), abs(p3.y - p1.y)); int new_width = max(abs(p1.x - p0.x), abs(p3.x - p2.x)); cout << "new_height = " << new_height << endl; cout << "new_width = " << new_width << endl; vector<Point2f> dst_point(4); dst_point[0] = Point(0,0); dst_point[1] = Point(new_width, 0); dst_point[2] = Point(0, new_height); dst_point[3] = Point(new_width, new_height); Mat resultImg; Mat wrap_mat = getPerspectiveTransform(src_point, dst_point); warpPerspective(image, resultImg, wrap_mat, Size(new_width, new_height)); imshow("resultImg", resultImg);}
关键步骤可视化 。
。
到此这篇关于OpenCV和C++实现图像的翻转(镜像)、平移、旋转、仿射与透视变换的文章就介绍到这了,更多相关OpenCV和C++图像翻转平移旋转内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://wangsp.blog.csdn.net/article/details/118694938 。
最后此篇关于OpenCV和C++实现图像的翻转(镜像)、平移、旋转、仿射与透视变换的文章就讲到这里了,如果你想了解更多关于OpenCV和C++实现图像的翻转(镜像)、平移、旋转、仿射与透视变换的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在尝试基于此示例实现 highcharts 平移: http://jsfiddle.net/HXUmK/5/ 但我希望能够用鼠标左键缩放并用鼠标右键平移。所以我修改了上面的代码并设法让它工作了一点
如何删除 BufferedImage 最左边垂直列的 50px,并将其复制到与原始 BufferedImage 大小相同的新 BufferedImage 中? class TestCopyImage
以下是关于如何绘制机器人的 ARM 和肩膀并通过一些用户输入旋转它们的代码(取自 http://www.glprogramming.com/red/chapter03.html ): glPushMa
我正在使用 Swift/SpriteKit 并在 SKScene 上创建了 map 的宽图像。我正在用代码完成这一切,并希望让用户拖动手指来平移这张超宽的 map 。可以将其想象为幻想世界的老式 RP
我正在将 opencv 与 C 一起使用,我正在尝试获取 2 个摄像头之间的外部参数(旋转和平移)。 有人告诉我可以使用棋盘格图案进行校准,但我找不到任何好的样本。我该怎么做? 编辑 给出的建议是用棋
我正在尝试在 android 图库小部件中缩放/平移图像。图像覆盖整个屏幕。虽然我可以缩放/平移图库中的图像,但我无法滑动到下一张/上一张图像。单个图像的缩放和平移效果很好。 我从 Hello And
当允许平移时,所有鼠标事件上的 JavaFX ScrollPane Pane : scrollPane.setPannable(true); 如何限制 ScrollPane 仅在鼠标中间事件上平移,
我一直试图弄清楚如何在 paperjs 中使用 onMouseDrag 和 onMouseDown 进行平移/缩放。 我看到的唯一引用是在 coffescript 中,并且不使用 paperjs 工具
我正在使用 d3 来渲染简化的甘特图,并使用 d3.behavior.zoom 进行平移和缩放。 x 比例是一个时间比例(稍微修改为以列为中心的日历天等)并且工作得很好,但是我在决定如何缩放/平移 y
我已经使用关键帧为HTML/CSS3创建了动画。 动画是一个图标,该图标应该围绕其中心点旋转和缩放。 该动画可在Chrome中运行,但在Safari中,直到动画结束,它才能正确转换。 这是-定位到 s
我有一个在登录事件后调用的 TranslationService,在这个服务中我想初始化 $translateProvider.translation 但这个对象似乎无法在 app.config(..
滚动和平移有什么区别? 平移是否被识别为拖动图像/背景的 Action ,而滚动仅在您使用滚动条时? 而且,拖动和平移有什么区别? 当我拖动google maps的 map 时,哪个术语合适,拖动还是
当用户按下鼠标并移动它时,我试图平移 Canvas ,但由于某种我看不到的原因,它似乎不起作用。有什么想法吗? canvas.addEventListener('mousedown', onM
我正在拼命寻找一种用 Pyglet 控制声音(左右)平衡的方法。 我知道 3D 定位系统,但我真正想要的只是控制平移(类似于 -1:left 1:right),而 3D 系统在这种情况下会适得其反(
考虑以下两组点。我想找到最佳的 2D 平移和旋转,以对齐数据集蓝色和数据集橙色之间的最大数量的点,如果到另一个数据集中最近邻居的距离小于阈值,则认为该点对齐。 我知道这与“迭代最近点”算法有关,但在这
我正在尝试包含 @bumbeishvili 的 Convex Hull 实现( https://bl.ocks.org/bumbeishvili/f027f1b6664d048e894d19e54fe
我正在尝试在平移和缩放时使可缩放/拖动矩形不超出 svg 边界。我尝试基于此 example 来实现它,但我似乎无法让它工作。我创建了 this jsfiddle只有可缩放和可拖动的矩形。再一次,我试
UIScrollView 有一个内置的行为“directionLockEnabled”。 启用后,平移将尝试锁定到水平或垂直方向。但是当用户积极尝试对角滚动时 - 它仍然允许对角滚动。 我想删除对角滚
我正在编写一个 GUI,它将执行一些图形平移/旋转等操作。 我的问题是,当我尝试翻译我的图形时, (a) 整个屏幕都会平移,而不是我的一小块绘制区域 (b) 旧油漆留在那里,留下一个大油漆 Blob
我最近一直在做一个项目,作为我的作业。 好吧,言归正传,我有一个 Scene2D 的 Screen 实现,我遇到的问题是我在小部件上的触摸事件不会在小部件上停止。 我的意思是,如果我弹出一个窗口,并尝
我是一名优秀的程序员,十分优秀!