代码:对鱼眼相机图像进行去畸变处理

图像投影模型:针孔[fx, fy, cx, cy]
图像畸变模型:切向径向畸变[k1, k2, p1, p2]
说明:用于备忘

  1. 第一部分是常规的去畸变操作,在已知内参的情况下对鱼眼相机进行去畸变,这里使用的是remap映射
  2. 在对图像去畸变后,对于图像边缘的像素全部造成了丢失,所以进行了一次没有意义的尝试,想尽可能的保留图像边缘像素,实现后发现边缘像素部分比较模糊而且还对中心位置的去畸变效果造成了影响

图像来源和参考链接:https://github.com/HLearning/fisheye

1.第一部分:常规去畸变操作

因为只是一个简单验证,所以将内参、图像加载路径和保存路径都写在了代码里面
代码片段:

    cv::Mat K = (cv::Mat_<double>(3, 3) << 652.8609862494474, 0.0, 1262.1021584894233,0.0, 653.1909758659955, 928.0871455436396,0.0, 0.0, 1.0);cv::Mat D = (cv::Mat_<double>(4, 1) << -0.024092199861108887, 0.002745976275100771, 0.002545415522352827, -0.0014366825722748522);cv::Mat raw_image = cv::imread("../data/pig.jpg");cout << raw_image.cols  << " " << raw_image.rows << endl;int width = raw_image.cols;int height = raw_image.rows;cv::Mat map1, map2;cv::Mat undistortImg;cv::Size imageSize(width, height);cv::fisheye::initUndistortRectifyMap(K, D, cv::Mat(), K, imageSize, CV_16SC2, map1, map2);cv::remap(raw_image, undistortImg, map1, map2, cv::INTER_LINEAR, cv::BORDER_CONSTANT);cv::imwrite("../data/dst.png", undistortImg);

原图像和结果如下,因为remap函数要求输入与输出的图像大小一致,所以这个过程造成了信息丢失,边缘部分的小猪崽们都缺少了很多
在这里插入图片描述

2.第二部分:保留图像边界信息

思路很简单,既然像素丢失是因为在remap后像素坐标超出了边界,那直接对原图像进行扩边处理再去畸变就好了,图像的高和宽分别为height,width,对图像的上下边界各扩充 1 4 ⋅ h e i g h t \frac{1}{4} \cdot height 41height个像素,对图像左右边界各扩充 1 4 ⋅ w i d t h \frac{1}{4} \cdot width 41width个像素

图像大小改变后,投影内参也要对应的改变,主要指像素坐标远点的偏移距离cx, cy,上下左右各增加了高和宽的1/4,所以整体上高和宽增加了1/2,即变为原来的1.5倍

扩边函数使用cv::copyMakeBorder

代码片段如下:

    // 扩边处理cv::Mat K_ = (cv::Mat_<double>(3, 3) << 652.8609862494474, 0.0, 1.5 * 1262.1021584894233,0.0, 653.1909758659955, 1.5 * 928.0871455436396,0.0, 0.0, 1.0);cv::Mat D_ = (cv::Mat_<double>(4, 1) << -0.024092199861108887, 0.002745976275100771, 0.002545415522352827, -0.0014366825722748522);int width_ = raw_image.cols + raw_image.cols/2;int height_ = raw_image.rows + raw_image.rows/2;cv::Mat temp(height_, width_, raw_image.type());cv::copyMakeBorder(raw_image, temp, raw_image.rows/4, raw_image.rows/4, raw_image.cols/4, raw_image.cols/4, cv::BORDER_ISOLATED);cout << temp.cols  << " " << temp.rows << endl;cv::imwrite("../data/src2.png", temp);cv::Mat map3, map4;cv::Mat undistortImg_;cv::Size imageSize_(width_, height_);cv::fisheye::initUndistortRectifyMap(K_, D_, cv::Mat(), K_, imageSize_, CV_16SC2, map3, map4);cv::remap(temp, undistortImg_, map3, map4, cv::INTER_LINEAR, cv::BORDER_CONSTANT);cv::imwrite("../data/dst2.png", undistortImg_);

结果如下,可以看到图像边界部分的像素保留的更多了:
在这里插入图片描述

3.讨论

但是这种思路是错误的,因为在对图像扩边处理后,进行remap的输入图像发生了变化,remap映射要对扩边后的整个图像处理,这样会影响图像中心区域的去畸变效果,如果继续增加扩便的大小,比如将增加的边界由原来高和宽的1/4变为高和宽的1/2,会很明显的发现中心区域的去畸变效果受到影响(两条栏杆变的更弯了),这不是我们想要的。

正确的做法是在remap中做文章,在函数中新建一个大的空白图像,将去畸变后的像素映射到该图像上的对应位置,在remap结束后返回这张图像

4.完整代码

源代码文件fisheye.cpp

#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/imgproc/imgproc.hpp>using namespace std;
// using namespace cv;int main(int argc, char **argv)
{cv::Mat K = (cv::Mat_<double>(3, 3) << 652.8609862494474, 0.0, 1262.1021584894233,0.0, 653.1909758659955, 928.0871455436396,0.0, 0.0, 1.0);cv::Mat D = (cv::Mat_<double>(4, 1) << -0.024092199861108887, 0.002745976275100771, 0.002545415522352827, -0.0014366825722748522);cv::Mat raw_image = cv::imread("../data/pig.jpg");cout << raw_image.cols  << " " << raw_image.rows << endl;int width = raw_image.cols;int height = raw_image.rows;cv::Mat map1, map2;cv::Mat undistortImg;cv::Size imageSize(width, height);cv::fisheye::initUndistortRectifyMap(K, D, cv::Mat(), K, imageSize, CV_16SC2, map1, map2);cv::remap(raw_image, undistortImg, map1, map2, cv::INTER_LINEAR, cv::BORDER_CONSTANT);cv::imwrite("../data/dst.png", undistortImg);// 扩边处理cv::Mat K_ = (cv::Mat_<double>(3, 3) << 652.8609862494474, 0.0, 1.5 * 1262.1021584894233,0.0, 653.1909758659955, 1.5 * 928.0871455436396,0.0, 0.0, 1.0);cv::Mat D_ = (cv::Mat_<double>(4, 1) << -0.024092199861108887, 0.002745976275100771, 0.002545415522352827, -0.0014366825722748522);int width_ = raw_image.cols + raw_image.cols/2;int height_ = raw_image.rows + raw_image.rows/2;cv::Mat temp(height_, width_, raw_image.type());cv::copyMakeBorder(raw_image, temp, raw_image.rows/4, raw_image.rows/4, raw_image.cols/4, raw_image.cols/4, cv::BORDER_ISOLATED);cout << temp.cols  << " " << temp.rows << endl;cv::imwrite("../data/src2.png", temp);cv::Mat map3, map4;cv::Mat undistortImg_;cv::Size imageSize_(width_, height_);cv::fisheye::initUndistortRectifyMap(K_, D_, cv::Mat(), K_, imageSize_, CV_16SC2, map3, map4);cv::remap(temp, undistortImg_, map3, map4, cv::INTER_LINEAR, cv::BORDER_CONSTANT);cv::imwrite("../data/dst2.png", undistortImg_);return 0;
}

CMakeLists.txt文件

cmake_minimum_required(VERSION 2.8)project(fisheye_cali)find_package(OpenCV REQUIRED)include_directories(${OpenCV_INCLUDE_DIRS})add_executable(${PROJECT_NAME} fisheye.cpp)
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/149148.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

竞赛 机器视觉的试卷批改系统 - opencv python 视觉识别

文章目录 0 简介1 项目背景2 项目目的3 系统设计3.1 目标对象3.2 系统架构3.3 软件设计方案 4 图像预处理4.1 灰度二值化4.2 形态学处理4.3 算式提取4.4 倾斜校正4.5 字符分割 5 字符识别5.1 支持向量机原理5.2 基于SVM的字符识别5.3 SVM算法实现 6 算法测试7 系统实现8 最后 0…

Windows下启动freeRDP并自适应远端桌面大小

几个二进制文件 xfreerdp # Linux下的&#xff0c;an X11 Remote Desktop Protocol (RDP) client which is part of the FreeRDP project wfreerdp.exe # Windows下的&#xff0c;freerdp2.0 主程序&#xff0c;freerdp3.0将废弃 sdl-freerdp.exe # Windows下的&…

appscan的两种手动探索扫描方式

文章目录 一、使用火狐FoxyProxy浏览器代理探索二、使用appscan内置浏览器探索 一、使用火狐FoxyProxy浏览器代理探索 首先火狐浏览器需安装FoxyProxy 先在扩展和主题里搜FoxyProxy 选FoxyProxy Standard,然后添加到浏览器就行 添加后浏览器右上角会有这个插件 打开apps…

【算法学习】-【双指针】-【快乐数】

LeetCode原题链接&#xff1a;202. 快乐数 下面是题目描述&#xff1a; 「快乐数」 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。 然后重复这个过程直到这个数变为 1&#xff0c;也可能是 无限循环 但始终变不到 1。 如果…

cad图纸如何防止盗图(一个的制造设计型企业如何保护设计图纸文件)

在现代企业中&#xff0c;设计图纸是公司的重要知识产权&#xff0c;关系到公司的核心竞争力。然而&#xff0c;随着技术的发展&#xff0c;员工获取和传播设计图纸的途径越来越多样化&#xff0c;如何有效地防止员工复制设计图纸成为了企业管理的一大挑战。本文将从技术、管理…

【动手学深度学习-Pytorch版】Transformer代码总结

本文是纯纯的撸代码讲解&#xff0c;没有任何Transformer的基础内容~ 是从0榨干Transformer代码系列&#xff0c;借用的是李沐老师上课时讲解的代码。 本文是根据每个模块的实现过程来进行讲解的。如果您想获取关于Transformer具体的实现细节&#xff08;不含代码&#xff09;可…

MySQL的复合查询

文章目录 1. 多表查询2. 自连接3. 子查询3.1 单行子查询3.2 多行单列子查询3.3 单行多列子查询3.4 在from子句中使用子查询 4. 合并查询4.1 union all4.2 union 5. 内连接6. 外连接6.1 左外连接6.2 右外连接 1. 多表查询 前面我们讲解的mysql表的查询都是对一张表进行查询&…

哨兵(Sentinel-1、2)数据下载

哨兵&#xff08;Sentinel-1、2&#xff09;数据下载 一、登陆欧空局网站 二、检索 先下载2号为光学数据 分为S2A和S2B&#xff0c;产品种类有1C和2A&#xff0c;区别就是2A是做好大气校正的影像&#xff0c;当然数量也会少一些&#xff0c;云量检索条件中记得要按格式&#x…

Mind Map:大语言模型中的知识图谱提示激发思维图10.1+10.2

知识图谱提示激发思维图 摘要介绍相关工作方法第一步&#xff1a;证据图挖掘第二步&#xff1a;证据图聚合第三步&#xff1a;LLM Mind Map推理 实验实验设置医学问答长对话问题使用KG的部分知识生成深入分析 总结 摘要 LLM通常在吸收新知识的能力、generation of hallucinati…

一键AI高清换脸——基于InsightFace、CodeFormer实现高清换脸与验证换脸后效果能否通过人脸比对、人脸识别算法

前言 1、项目简介 AI换脸是指利用基于深度学习和计算机视觉来替换或合成图像或视频中的人脸。可以将一个人的脸替换为另一个人的脸,或者将一个人的表情合成到另一个人的照片或视频中。算法常常被用在娱乐目上,例如在社交媒体上创建有趣的照片或视频,也有用于电影制作、特效…

Qt model/view 理解01

在 Qt 中对数据处理主要有两种方式&#xff1a;1&#xff09;直接对包含数据的的数据项 item 进行操作&#xff0c;这种方法简单、易操作&#xff0c;现实方式单一的缺点&#xff0c;特别是对于大数据或在不同位置重复出现的数据必须依次对其进行操作&#xff0c;如果现实方式改…

44 二叉搜索树中第K个小的元素

二叉搜索树中第K个小的元素 题解1 中序遍历题解2 AVL&#xff08;手撕平衡二叉树&#xff1a;谢谢力扣官方&#xff09; 给定一个二叉搜索树的根节点 root &#xff0c;和一个整数 k &#xff0c;请你设计一个算法查找其中第 k 个最小元素&#xff08;从 1 开始计数&#xf…

再来介绍另一个binlog文件解析的第三方工具my2sql

看腻了文字就来听听视频演示吧&#xff1a;https://www.bilibili.com/video/BV1rp4y1w74B/ github项目&#xff1a;https://github.com/liuhr/my2sql gitee链接&#xff1a;https://gitee.com/mirrors/my2sql my2sql go版MySQL binlog解析工具&#xff0c;通过解析MySQL bin…

Maven 中引用其他项目jar包出现BOOT-INF问题

问题 在B项目中引入A项目的类&#xff0c;但是发现怎么也引入不进来 A项目打包之后&#xff0c;想在B项目中引用jar 在B项目中发现类文件无法引用 参考网上进行清缓存等一系列操作都没有解决。 最后发现引用的jar包中包含BOOT-INF&#xff0c; 然后去A项目中查找&#xff…

基于回溯搜索优化的BP神经网络(分类应用) - 附代码

基于回溯搜索优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录 基于回溯搜索优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.回溯搜索优化BP神经网络3.1 BP神经网络参数设置3.2 回溯搜索算法应用 4.测试结果…

基于MFC和OpenCV实现人脸识别

基于MFC和OpenCV实现人脸识别 文章目录 基于MFC和OpenCV实现人脸识别1. 项目说明1. 创建项目2. 启动窗口3. 登录窗口-添加窗口、从启动窗口跳转4. 启动窗口-美化按钮5. 登录窗口-美化按钮、雪花视频6. 注册窗口-美化按钮、雪花视频、从启动窗口跳转7. 注册窗口-开启摄像头8. 注…

大恒IFrameData IImageData转bmp HObject Mat

大恒工业相机采集的帧数据转为其他8bit图像格式 C#转为bmp格式转为Halcon的HObject格式转为OpenCVSharp的Mat格式 回调采集图像的数据类型为IFrameData&#xff0c;单帧采集的数据类型为IImageData&#xff0c;两者的区别为IImageData类多了一个**Destroy()**方法 C# 转为bm…

C++标准模板(STL)- 类型支持 (定宽整数类型)(int8_t,int_fast8_t,int_least8_t,intmax_t,intptr_t)

定宽整数类型 类型 定义于头文件 <cstdint> int8_tint16_tint32_tint64_t (可选) 分别为宽度恰为 8、16、32 和 64 位的有符号整数类型 无填充位并对负值使用补码 &#xff08;仅若实现支持该类型才提供&#xff09; (typedef) int_fast8_tint_fast16_tint_fast32_tint…

第二章 线性表

线性表 线性表的基本概念线性表的顺序存储线性表顺序存储的类型定义线性表基本运算在顺序表上的实现顺序表实现算法的分析 线性表的链接存储单链表的类型定义线性表的基本运算在单链表上的实现 其他运算在单链表上的实现建表删除重复结点 其他链表循环链表双向循环链表 顺序实现…

如何将图片存到数据库(以mysql为例), 使用ORM Bee更加简单

如何将图片存到数据库 1. 创建数据库: 2. 生成Javabean public class ImageExam implements Serializable {private static final long serialVersionUID 1596686274309L;private Integer id;private String name; // private Blob image;private InputStream image; //将In…