银行卡矫正(透视变换)

编程入门 行业动态 更新时间:2024-10-10 14:28:51

<a href=https://www.elefans.com/category/jswz/34/1750008.html style=银行卡矫正(透视变换)"/>

银行卡矫正(透视变换)

项目介绍–银行卡矫正(透视变换)

			实现银行卡变换形状,给图片拉正

示例图:

实现思路:

1.读取图片

2.灰度图

3.canny边缘检测

4.霍夫直线检测

5.画出找到的四条直线

6.判断四条直线位置

7.求四条直线交点

8.获取交点存为矩阵

9.新矩阵的四个顶点

10.进行透视变换

代码实现:

#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;int main()
{/*一般检测边缘  在灰度图检测检测轮廓   在二值图*/Mat srcimg = imread("C:\\Users\\20435\\Desktop\\tu\\1.jpg");imshow("【原图】", srcimg);Mat grayimg;cvtColor(srcimg, grayimg, COLOR_RGB2GRAY);imshow("【灰度】", grayimg);Mat bimg, gauess_img, bf_img,kernel;GaussianBlur(grayimg, gauess_img, Size(5, 5), 0, 0);imshow("高斯", gauess_img);/*  2图用到的二值化  THRESH_BINARY_INV  *///adaptiveThreshold(grayimg, bimg, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, 501, 0);//imshow("二值图", bimg);Mat canny_img;//小于a不是边缘   大于b是边缘   a-b根据连通性 决定是否为边缘Canny(gauess_img, canny_img, 80, 120);imshow("边缘", canny_img);Mat dd_img;dilate(canny_img, dd_img, kernel, Point(-1, -1));imshow("边缘后膨胀", dd_img);//检测完边缘过后  尝试检测一下轮廓(效果不错先保留)vector<vector<Point>> countor;vector<Vec4i> arrtype;findContours(dd_img, countor, arrtype, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);Mat zero_img = Mat::zeros(dd_img.size(), CV_8UC3);for (int i = 0; i < countor.size(); i++){Rect rect = boundingRect(countor[i]);drawContours(zero_img, countor, static_cast<int>(i), Scalar(255, 0, 0), 2, 8, arrtype);}imshow("轮廓", zero_img);//进行找直线/*1.把轮廓图  找直线2.创建空图3.把找到的直线 绘制到空图中*/vector<Vec4i> lines;int width = zero_img.cols;int height = zero_img.rows;cvtColor(zero_img, zero_img, COLOR_BGR2GRAY);int accu = min(width * 0.15, height * 0.3);   /*  后三个参数  大于这个才可以被返回    大于这个才可以被显示出来    中间最大空缺直线*/HoughLinesP(zero_img, lines, 1, CV_PI / 270, accu, 150, 20);Mat linesImage = Mat::zeros(dd_img.size(), CV_8UC3);for (size_t t = 0; t < lines.size(); t++){Vec4i ln = lines[t];line(linesImage, Point(ln[0], ln[1]), Point(ln[2], ln[3]), Scalar(0, 0, 255), 2, 8, 0);}imshow("linesImage", linesImage);//来确定上下左右四条直线int line_temp;Vec4i top_line, bottom_line;Vec4i left_line, right_line;//循环你找到的所有线for (int i = 0; i < lines.size();i++){Vec4i temp = lines[i];line_temp = abs(temp[3] - temp[1]);if (temp[1] <= height/2  &&  temp[3] <= height / 2 && line_temp <= accu - 1){top_line = lines[i];}if(temp[1] >= height / 2 && temp[3] >= height / 2 && line_temp <= accu - 1){bottom_line = lines[i];}if (temp[0] <= width / 2 && temp[2] <= width / 2){left_line = lines[i];}if (temp[0] >= width / 2 && temp[2] >= width / 2){right_line = lines[i];}}cout << "width / 2=" << width / 2 << endl;cout << "height / 2=" << height / 2 << endl;cout << "top_line" << "顶点坐标(x1,y1=)" << top_line[0] << "," << top_line[1] << "   终点坐标(x2,y2=)" << top_line[2] << "," << top_line[3] << endl;cout << "bottom_line" << "顶点坐标(x1,y1=)" << bottom_line[0] << "," << bottom_line[1] << "   终点坐标(x2,y2=)" << bottom_line[2] << "," << bottom_line[3] << endl;cout << "left_line" << "顶点坐标(x1,y1=)" << left_line[0] << "," << left_line[1] << "   终点坐标(x2,y2=)" << left_line[2] << "," << left_line[3] << endl;cout << "right_line" << "顶点坐标(x1,y1=)" << right_line[0] << "," << right_line[1] << "   终点坐标(x2,y2=)" << right_line[2] << "," << right_line[3] << endl;// 拟合四条直线方程,求直线相交的点float k1, c1;k1 = float(top_line[3] - top_line[1]) / float(top_line[2] - top_line[0]);c1 = top_line[1] - k1 * top_line[0];float k2, c2;k2 = float(bottom_line[3] - bottom_line[1]) / float(bottom_line[2] - bottom_line[0]);c2 = bottom_line[1] - k2 * bottom_line[0];float k3, c3;k3 = float(left_line[3] - left_line[1]) / float(left_line[2] - left_line[0]);c3 = left_line[1] - k3 * left_line[0];float k4, c4;k4 = float(right_line[3] - right_line[1]) / float(right_line[2] - right_line[0]);c4 = right_line[1] - k4 * right_line[0];// 四条直线交点Point p1; // 左上角p1.x = static_cast<int>((c1 - c3) / (k3 - k1));p1.y = static_cast<int>(k1 * p1.x + c1);Point p2; // 右上角p2.x = static_cast<int>((c1 - c4) / (k4 - k1));p2.y = static_cast<int>(k1 * p2.x + c1);Point p3; // 左下角p3.x = static_cast<int>((c2 - c3) / (k3 - k2));p3.y = static_cast<int>(k2 * p3.x + c2);Point p4; // 右下角p4.x = static_cast<int>((c2 - c4) / (k4 - k2));p4.y = static_cast<int>(k2 * p4.x + c2);cout << "p1(x, y)=" << p1.x << "," << p1.y << endl;cout << "p2(x, y)=" << p2.x << "," << p2.y << endl;cout << "p3(x, y)=" << p3.x << "," << p3.y << endl;cout << "p4(x, y)=" << p4.x << "," << p4.y << endl;// 显示四个点坐标circle(linesImage, p1, 2, Scalar(255, 0, 0), 2, 8, 0);circle(linesImage, p2, 2, Scalar(255, 0, 0), 2, 8, 0);circle(linesImage, p3, 2, Scalar(255, 0, 0), 2, 8, 0);circle(linesImage, p4, 2, Scalar(255, 0, 0), 2, 8, 0);line(linesImage, Point(top_line[0], top_line[1]), Point(top_line[2], top_line[3]), Scalar(0, 255, 0), 2, 8, 0);imshow("four corners", linesImage);// 透视变换vector<Point2f> src_corners(4);src_corners[0] = p1;src_corners[1] = p2;src_corners[2] = p3;src_corners[3] = p4;vector<Point2f> dst_corners(4);dst_corners[0] = Point(0, 0);dst_corners[1] = Point(width, 0);dst_corners[2] = Point(0, height);dst_corners[3] = Point(width, height);// 获取透视变换矩阵Mat resultImage;Mat warpmatrix = getPerspectiveTransform(src_corners, dst_corners);warpPerspective(srcimg, resultImage, warpmatrix, resultImage.size(), INTER_LINEAR);imshow("Final Result", resultImage);waitKey(0);
}

参考网址

.html

更多推荐

银行卡矫正(透视变换)

本文发布于:2024-02-07 12:10:20,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1756897.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:银行卡   透视

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!