#include <iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc.hpp>
#include<Eigen/Dense>
#include<Eigen/SVD>
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <vector>
namespace py = pybind11;
using namespace std;
#define MAXFLOAT std::numeric_limits<double>::max()
template <typename T>
cv::Point_<T> applyTransform2x3(T x, T y, const cv::Mat& matT) {
return cv::Point_<T>((matT.at<double>(0, 0) * x + matT.at<double>(0, 1) * y + matT.at<double>(0, 2)),
(matT.at<double>(1, 0) * x + matT.at<double>(1, 1) * y + matT.at<double>(1, 2)));
}
py::array_t<uint> texture_mapping(py::array_t<float>& origin_vertice, py::array_t<float> transformed_vertices, py::array_t<uint>& pre_align_picture) {
//由于需要用到opencv的fillpoly,applyTransform2x3,getAffineTransform函数,因此先把数据转换为opencv的格式
auto r1 = origin_vertice.unchecked<3>();
auto r2 = transformed_vertices.unchecked<3>();
auto r3 = pre_align_picture.unchecked<3>();
//确定偏移的大小
int shift_x = 0;
int shift_y = 0;
int origin_rows = pre_align_picture.shape()[0];
int origin_cols = pre_align_picture.shape()[1];
//图片转换到opencv
cv::Mat origin(cv::Size(pre_align_picture.shape()[0], pre_align_picture.shape()[1]), CV_8UC3);
for (int row = 0; row < pre_align_picture.shape()[0]; row++) {
for (int col = 0; col < pre_align_picture.shape()[1]; col++) {
origin.at<cv::Vec3b>(row, col) = cv::Vec3b(r3(row, col, 0), r3(row, col, 1), r3(row, col, 2));
}
}
//获取3角形,一共有方块的个数乘以二个
vector<vector<cv::Point2f>> origin_triangles;
origin_triangles.reserve((origin_vertice.shape()[0] - 1) * (origin_vertice.shape()[1] * 2));
for (int row = 0; row < origin_vertice.shape()[0] - 1; row++) {
for (int col = 0; col < origin_vertice.shape()[1] - 1; col++) {
vector<cv::Point2f> triangle1(3), triangle2(3);
triangle1[0] = cv::Point2f(r1(row, col, 0), r1(row, col, 1));
triangle1[1] = cv::Point2f(r1(row, col + 1, 0), r1(row, col + 1, 1));
triangle1[2] = cv::Point2f(r1(row + 1, col, 0), r1(row + 1, col, 1));
origin_triangles.emplace_back(triangle1);
triangle2[0] = cv::Point2f(r1(row, col + 1, 0), r1(row, col + 1, 1));
triangle2[1] = cv::Point2f(r1(row + 1, col + 1, 0), r1(row + 1, col + 1, 1));
triangle2[2] = cv::Point2f(r1(row + 1, col, 0), r1(row + 1, col, 1));
origin_triangles.emplace_back(triangle2);
}
}
//求取画布的信息
float minx = MAXFLOAT, miny = MAXFLOAT, maxy = -MAXFLOAT, maxx = -MAXFLOAT;
for (int row = 0; row < transformed_vertices.shape()[0]; row++) {
for (int col = 0; col < transformed_vertices.shape()[1]; col++) {
minx = min(r2(row, col, 0), minx);
miny = min(r2(row, col, 1), miny);
maxx = max(r2(row, col, 0), maxx);
maxy = max(r2(row, col, 1), maxy);
}
}
//maxx = max(maxx, origin_cols);
//maxy = max(maxy, origin_rows);
cv::Rect canvas;
canvas.height = int(maxy - miny);
canvas.width = int(maxx - minx);
canvas.x = int(minx);
canvas.y = int(miny);
if (canvas.x < 0) {
shift_x = abs(canvas.x);
}
if (canvas.y < 0)
{
shift_y = abs(canvas.y);
}
cout << "get canvas success success ..." << "the start of canvas is:" << "x:" << canvas.x << "y:" << canvas.y << "the height is " << canvas.height << "the width is :" << canvas.width << endl;
//进行投影,首先确定最终图片的大小
int img_rows = max(int(maxy), origin_rows) + shift_y;
int img_cols = max(int(maxx), origin_cols) + shift_x;
//与上面一样,只不过采取的顶点集不一样,
vector<vector<cv::Point2f>> transformed_triangles;
transformed_triangles.reserve((origin_vertice.shape()[0] - 1) * (origin_vertice.shape()[1] * 2));
for (int row = 0; row < origin_vertice.shape()[0] - 1; row++) {
for (int col = 0; col < origin_vertice.shape()[1] - 1; col++) {
vector<cv::Point2f> triangle1(3), triangle2(3);
triangle1[0] = cv::Point2f(r2(row, col, 0) + shift_x, r2(row, col, 1) + shift_y);
triangle1[1] = cv::Point2f(r2(row, col + 1, 0) + shift_x, r2(row, col + 1, 1) + shift_y);
triangle1[2] = cv::Point2f(r2(row + 1, col, 0) + shift_x, r2(row + 1, col, 1) + shift_y);
transformed_triangles.emplace_back(triangle1);
triangle2[0] = cv::Point2f(r2(row, col + 1, 0) + shift_x, r2(row, col + 1, 1) + shift_y);
triangle2[1] = cv::Point2f(r2(row + 1, col + 1, 0) + shift_x, r2(row + 1, col + 1, 1) + shift_y);
triangle2[2] = cv::Point2f(r2(row + 1, col, 0) + shift_x, r2(row + 1, col, 1) + shift_y);
transformed_triangles.emplace_back(triangle2);
}
}
//对于每一个三角形获取其变换
vector<cv::Mat> affine_transforms;
for (int i = 0; i < origin_triangles.size(); i++) {
cv::Point2f origin[3];
cv::Point2f tranformed[3];
for (int j = 0; j < 3; j++) {
origin[j] = origin_triangles[i][j];
tranformed[j] = transformed_triangles[i][j];
}
cv::Mat matrix = cv::getAffineTransform(tranformed, origin);
cv::Point2f dst = applyTransform2x3<float>(tranformed[0].x, tranformed[0].y, matrix);
//cout << "origin" << origin[0].x << origin[0].y << "dst" << dst.x << dst.y << endl;
affine_transforms.emplace_back(matrix);
}
cout << "get transform success " << endl;
//创建画布,并按顺序填充三角形
cv::Mat my_mask(cv::Size(img_cols, img_rows), CV_32SC1, cv::Scalar::all(-1));
for (int i = 0; i < transformed_triangles.size(); i++) {
cv::Point2i my_contour[3];
for (int j = 0; j < 3; j++) {
my_contour[j] = transformed_triangles[i][j];
}
cv::fillConvexPoly(my_mask, my_contour, 3, i, 16, 0);
}
cout << "fillConvexPoly success " << endl;
// 这个不用投影全图,只需填充
cv::Mat result(cv::Size(img_cols, img_rows), CV_8UC3);
for (int row = canvas.y + shift_y; row < canvas.y + shift_y + canvas.height; row++) {
for (int col = canvas.x + shift_x; col < canvas.x + shift_x + canvas.width; col++) {
//cout << "step1 ";
if (my_mask.at<int>(row, col) != -1) {
//cout << "step2 ";
int index = my_mask.at<int>(row, col);
cv::Mat affine_matrix = affine_transforms[index];
//cout << "step3 ";
cv::Point2f dst = applyTransform2x3<float>(col, row, affine_matrix);
//cout << "step4 ";
if ((dst.x >= 0 && int(dst.x) < pre_align_picture.shape()[1]) && (dst.y >= 0 && int(dst.y) < pre_align_picture.shape()[0])) {
//cout << int(dst.x) << int(dst.y);
result.at<cv::Vec3b>(row, col) = cv::Vec3b(r3(int(dst.y), int(dst.x), 0),
r3(int(dst.y), int(dst.x), 1),
r3(int(dst.y), int(dst.x), 2));
}
}
//cout << "step5" << endl;
}
}
cout << "perspective success" << endl;
py::array_t<uint> output = py::array_t<uint>(img_rows * img_cols * 3);
output.resize({ img_rows, img_cols,3 });
auto r8 = output.mutable_unchecked<3>();
cout << result.cols << result.rows << output.shape()[1] << output.shape()[0] << canvas.height << canvas.width << endl;
for (int row = 0; row < output.shape()[0]; row++) {
for (int col = 0; col < output.shape()[1]; col++) {
for (int channel = 0; channel < output.shape()[2]; channel++) {
uint value = result.at<cv::Vec3b>(row, col)[channel];
//cout << "value" << value << endl;
r8(row, col, channel) = value;
}
}
}
return output;
}
PYBIND11_MODULE(texture_mapping, m) {
m.def("texture_mapping", &texture_mapping);
}
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
图像拼接领域论文Direct_Photometric_Alignment_by_Mesh_Deformation复现代码,python实现,image stitching。通过网格变形直接光学配准。 文章地址:https://blog.csdn.net/qq_36584673/article/details/122300266
资源推荐
资源详情
资源评论
收起资源包目录
Direct_Photometric_Alignment_by_Mesh_Deformation-master.zip (33个子文件)
Direct_Photometric_Alignment_by_Mesh_Deformation-master
feature
__init__.py 0B
match.py 1KB
feature_point.py 426B
test.ipynb 3KB
optimization.dll 136KB
image
DSC00319.JPG 187KB
DSC00318.JPG 182KB
main.py 10KB
pyd_source
texture_mapping.cpp 7KB
optimization.cpp 5KB
mesh
bin_plo.py 2KB
bilinear_interpolation.py 2KB
get_triangle.py 389B
mesh.py 903B
.idea
$PRODUCT_WORKSPACE_FILE$ 1KB
other.xml 233B
misc.xml 634B
optical.iml 563B
inspectionProfiles
profiles_settings.xml 174B
modules.xml 266B
deployment.xml 1KB
.gitignore 38B
main_g.py 7KB
config.yaml 172B
optimization.pyd 136KB
texture_mapping.pyd 113KB
util
triangle_similar.py 869B
draw.py 2KB
gradient.py 13KB
blending_average.py 778B
image_info.py 2KB
transform.py 509B
get_param.py 594B
共 33 条
- 1
资源评论
- 2301_767926742024-12-01超级好的资源,很值得参考学习,对我启发很大,支持!
十小大
- 粉丝: 1w+
- 资源: 1529
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- awewq1132323
- 手写流程图检测31-YOLO(v5至v8)、COCO、CreateML、Darknet、Paligemma、TFRecord数据集合集.rar
- frida拦截微信小程序云托管API
- 肝脏及其肿瘤分割的 CT 数据集,已经切片成jpg数据,约2w张数据和mask
- 基于Java的网上教务评教管理系统的设计与实现.doc
- 2024圣诞节海外消费市场趋势及营销策略分析报告
- JWaaaaaaaaaaaaaaaaaaaa
- Python实现常见排序算法详解
- 等发达地区的无穷大无穷大无穷大请问
- 微藻检测19-YOLO(v5至v11)、COCO、CreateML、Paligemma、TFRecord、VOC数据集合集.rar
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功