《实时畸变校正》

2024-05-24 07:58
文章标签 实时 畸变 校正

本文主要是介绍《实时畸变校正》,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 摄像头畸变
  • 手眼标定
  • 实时畸变校正
    • cv2.undistort & cv2.initUndistortRectifyMap + cv2.remap
    • 显示区域
    • Error:[h264 @ 000001bf04177660] error while decoding MB 11 84, bytestream -17
  • 多线程实时实时校正
  • 多进程实时校正
  • 参考链接

摄像头畸变

​ 由于摄像头制造的不足以及成像过程中的噪声影响,摄像头成像往往不满足针孔模型,这种成像模型称为非线性模型。非线性模型中畸变主要有三种,包括径向畸变、切向畸变和薄棱镜畸变。假设理想的成像点坐标 ,畸变后的实际成像点坐标 ,则非线性畸变模型如下
{ x d = x u + δ x y d = y u + δ y \begin{cases} x_d = x_u + δ_x \\ y_d = y_u + δ_y \\ \end{cases} {xd=xu+δxyd=yu+δy

  • a) 径向畸变

图像的径向畸变是指像点相对理想位置发生向内或者向外的偏移,即像点在径向上出现误差。
{ δ x = x u ( k 1 r u 2 + k 2 r u 4 + k 3 r u 6 + . . . ) δ y = y u ( k 1 r u 2 + k 2 r u 4 + k 3 r u 6 + . . . ) \begin{cases} δ_x = x_u(k_1r_u^2 + k_2r_u^4 + k_3r_u^6 + ...)\\ δ_y = y_u(k_1r_u^2 + k_2r_u^4 + k_3r_u^6 + ...) \end{cases} {δx=xu(k1ru2+k2ru4+k3ru6+...)δy=yu(k1ru2+k2ru4+k3ru6+...)

式中, r u 2 = x u 2 + y u 2 r_u^2 = x_u^2+y_u^2 ru2=xu2+yu2 k 1 , k 2 , k 3 k_1,k_2,k_3 k1,k2,k3为径向畸变系数。

  • b) 切向畸变

图像的切向畸变是指由于光学系统的光学镜头装配产生误差,光轴不可能完全共线,即像点在切向上出现了偏差。
{ δ x = p 1 ( 3 x u 2 + y u 2 ) + 2 p 2 x u y u δ y = p 2 ( 3 y u 2 + x u 2 ) + 2 p 1 x u y u \begin{cases} δ_x = p_1(3x_u^2 + y_u^2) + 2p_2x_uy_u\\ δ_y = p_2(3y_u^2 + x_u^2) + 2p_1x_uy_u \end{cases} {δx=p1(3xu2+yu2)+2p2xuyuδy=p2(3yu2+xu2)+2p1xuyu
式中, p 1 , p 2 p_1,p_2 p1,p2为切向畸变系数。

  • c) 薄棱镜畸变

图像的薄棱镜畸变是指由光学镜头制造误差和成像敏感阵列制造误差引起的图像变形。
{ δ x = s 1 ( x u 2 + y u 2 ) δ y = s 1 ( x u 2 + y u 2 ) \begin{cases} δ_x = s_1(x_u^2+y_u^2)\\ δ_y = s_1(x_u^2+y_u^2)\\ \end{cases} {δx=s1(xu2+yu2)δy=s1(xu2+yu2)
式中, s 1 , s 2 s_1,s_2 s1,s2为薄棱镜畸变系数。

  • 畸变参数

    • 径向畸变 $ k_1, k_2, k_3$

    • 切向畸变 $ p_1, p_2$

    • 薄棱镜畸变 s 1 , s 2 s_1, s_2 s1,s2

  • (一般考虑OpenCV前五个参数, k 1 , k 2 , p 1 , p 2 , k 3 k_1, k_2, p_1, p_2, k_3 k1,k2,p1,p2,k3)镜头畸变中径向畸变(主要是前两阶的)和切向畸变影响较

大,占畸变的95%,而薄棱镜畸变会造成额外的径向畸变和切向畸变,影响较小。一般情况下,只需考虑径向畸变和切向畸变,薄棱镜畸往往忽略不计。

手眼标定

  • 视频取流
  • 按’S’交互保存标定板图片
  • 标定图片到一定数量后,按’C’标定
  • 按’Q’退出
def grab_web_cam(rtsp, path_img):VideoCapture = cv2.VideoCapture(rtsp)cv2.namedWindow(wnd_name, cv2.WINDOW_NORMAL)if not VideoCapture.isOpened():print("Error open video!")exit()save_num = 0while VideoCapture.isOpened():ret, frame = VideoCapture.read()if not ret:breakk = show_image("frame", frame, 1)if cv2.waitKey(1) & 0xFF == ord('q'):breakelif cv2.waitKey(1) & 0xFF == ord("s"):cv2.imencode(".jpg", frame)[1].tofile(os.path.join(path_img, "img_%04d.jpg" % save_num))save_num += 1print("save image:[%d]" % save_num)elif cv2.waitKey(1) & 0xFF == ord("c"):calib.calib(path_img, path_cfg)VideoCapture.release()

实时畸变校正

cv2.undistort & cv2.initUndistortRectifyMap + cv2.remap

  • mtx, dist, new_mtx分别为内参数,畸变系数,优化后的畸变系数

  • (1) 直接校正

    frame_rect = cv2.undistort(frame, mtx, dist, None, new_mtx)
    

请添加图片描述

  • (2) 先计算映射关系,再校正

    mapx, mapy = cv2.initUndistortRectifyMap(mtx, dist, None, new_mtx, (int(frame_width), int(frame_height)), 5)
    img_dst = cv2.remap(frame, mapx, mapy, interpolation=cv2.INTER_NEAREST, dst=None,borderMode=cv2.BORDER_CONSTANT, borderValue=(0, 0, 0))
    

请添加图片描述

  • 单独使用几次时,差别不大
  • 当多次图片畸变校正时,建议使用一次initUndistortRectifyMap,获取映射矩阵mapxmapy后,作为remap输入,再使用多次的remap校正
  • 实时畸变校正,帧率差距明显

显示区域

  • newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (img_gray.shape[1], img_gray.shape[0]), alpha, (width, height))

    • 优化相机内参(camera matrix),可选,提高精度
    • alpha= 1, 所有像素都保留,有黑色像素混入
    • alpha=0, 尽可能裁剪不想要的像素,都是有效,这是个scale
  • 边界填充

    • 畸变导致矫正后的图像边缘空缺

    • 可以通过remap里的borderMode来设置不同的填充效果

  • 有效区域裁剪

    • getOptimalNewCameraMatrix计算ROI
    • 矫正后的区域裁剪

Error:[h264 @ 000001bf04177660] error while decoding MB 11 84, bytestream -17

  • RTSP取流后,偶尔报错:

    [h264 @ 000001bf04177660] error while decoding MB 11 84, bytestream -17
    
  • 问题分析:H264除了使用帧内压缩之外,采用了独特的I帧、P帧和B帧策略来实现连续帧之间的压缩。在解码的时候如果不能有H264压缩时候需要的帧,就不能正确解码

  • 解决思路

    • (1)检查网络摄像头读取,失败后重启

          while (VideoCapture.isOpened()):ret, frame = VideoCapture.read()if not ret:VideoCapture = cv2.VideoCapture(rtsp)print("lost, have to reinitialization!")  continue
      
    • (2)取图和校正分开处理,多线程或多进程

多线程实时实时校正

  • 取图
  • 校正+显示
import cv2, os, time
import numpy as np
import threading, queuedef read_campara(path):with np.load(path) as X:data = [X[i] for i in ('mtx', 'dist', 'new_mtx', 'roi')]mtx, dist, new_mtx, roi = datareturn mtx, dist, new_mtx, roidef show(fps_enable = True, roi_enable=True):x, y, w, h = roicv2.namedWindow('undistort', cv2.WINDOW_NORMAL)while True:if not q.empty():frame = q.get()if fps_enable:timer = cv2.getTickCount()frame_rect = cv2.remap(frame, mapx, mapy, interpolation=cv2.INTER_NEAREST, dst=None,borderMode=cv2.BORDER_CONSTANT, borderValue=(0, 0, 0))if fps_enable:fps = cv2.getTickFrequency() / (cv2.getTickCount() - timer)print("FPS:{}".format(fps))if roi_enable:rect_roi = frame_rect[y:y + h, x:x + w]frame_roi = frame[y:y + h, x:x + w]img_stack = np.hstack([frame_roi, rect_roi])else:img_stack = np.hstack([frame, frame_rect])  # srcif fps_enable:cv2.putText(img_stack, "FPS : " + str(int(fps)), (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 255), 3)cv2.imshow('undistort', img_stack)if cv2.waitKey(1) & 0xFF == ord('q'):breakdef undistort_show_threads(rtsp, path_cfg, interval = 3):VideoCapture = cv2.VideoCapture(rtsp)while (VideoCapture.isOpened()):ret, frame = VideoCapture.read()if not ret:VideoCapture = cv2.VideoCapture(rtsp)print("lost, have to reinitialization!")  continuepos = VideoCapture.get(cv2.CAP_PROP_POS_FRAMES)if pos % interval != 0:continueq.put(frame)VideoCapture.release()if __name__ == "__main__":path_cfg = r"./cfg/cam2.npz"rtsp = 'rtsp://admin:123456@192.168.*.*'frame_width = 2560frame_height = 1440mtx, dist, new_mtx, roi = read_campara(path_cfg)mapx, mapy = cv2.initUndistortRectifyMap(mtx, dist, None, new_mtx, (int(frame_width), int(frame_height)), 5)q = queue.Queue()t1 = threading.Thread(target=undistort_show_threads, args=(rtsp, path_cfg))t2 = threading.Thread(target = show)t1.start()t2.start()t1.join()t2.join()

多进程实时校正

  • 取图
  • 校正+显示
import cv2, multiprocessing
import numpy as npdef read_campara(path):with np.load(path) as X:data = [X[i] for i in ('mtx', 'dist', 'new_mtx', 'roi')]mtx, dist, new_mtx, roi = datareturn mtx, dist, new_mtx, roidef show(queue, roi, mapx, mapy, fps_enable = True, roi_enable = True):x, y, w, h = roicv2.namedWindow('undistort', cv2.WINDOW_NORMAL)while True:if not queue.empty():frame = queue.get()if fps_enable:timer = cv2.getTickCount()frame_rect = cv2.remap(frame, mapx, mapy, interpolation=cv2.INTER_NEAREST, dst=None,borderMode=cv2.BORDER_CONSTANT, borderValue=(0, 0, 0))if fps_enable:fps = cv2.getTickFrequency() / (cv2.getTickCount() - timer)print("FPS:{}".format(fps))if roi_enable:rect_roi = frame_rect[y:y + h, x:x + w]frame_roi = frame[y:y + h, x:x + w]img_stack = np.hstack([frame_roi, rect_roi])else:img_stack = np.hstack([frame, frame_rect])  # srcif fps_enable:cv2.putText(img_stack, "FPS : " + str(int(fps)), (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 255), 3)cv2.imshow('undistort', img_stack)if cv2.waitKey(1) & 0xFF == ord('q'):breakdef undistort_show_processes(queue, rtsp, path_cfg, interval = 3):VideoCapture = cv2.VideoCapture(rtsp)while (VideoCapture.isOpened()):ret, frame = VideoCapture.read()if not ret:VideoCapture = cv2.VideoCapture(rtsp)print("lost, have to reinitialization!")  continuepos = VideoCapture.get(cv2.CAP_PROP_POS_FRAMES)if pos % interval != 0:continuequeue.put(frame)VideoCapture.release()if __name__ == "__main__":path_cfg = r"./cfg/cam2.npz"rtsp = 'rtsp://admin:123455@192.168.*.*'frame_width = 2560frame_height = 1440mtx, dist, new_mtx, roi = read_campara(path_cfg)mapx, mapy = cv2.initUndistortRectifyMap(mtx, dist, None, new_mtx, (int(frame_width), int(frame_height)), 5)multiprocessing.set_start_method(method='spawn')  # initqueue = multiprocessing.Queue(maxsize=4)processes = []processes.append(multiprocessing.Process(target = undistort_show_processes, args=(queue, rtsp, path_cfg)))processes.append(multiprocessing.Process(target = show, args = (queue, roi, mapx, mapy)))for process in processes:process.daemon = Trueprocess.start()for process in processes:process.join()

参考链接

opencv read error:[h264 @ 0x8f915e0] error while decoding MB 53 20, bytestream -7

这篇关于《实时畸变校正》的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/997823

相关文章

Java五子棋之坐标校正

上篇针对了Java项目中的解构思维,在这篇内容中我们不妨从整体项目中拆解拿出一个非常重要的五子棋逻辑实现:坐标校正,我们如何使漫无目的鼠标点击变得有序化和可控化呢? 目录 一、从鼠标监听到获取坐标 1.MouseListener和MouseAdapter 2.mousePressed方法 二、坐标校正的具体实现方法 1.关于fillOval方法 2.坐标获取 3.坐标转换 4.坐

YOLOv9摄像头或视频实时检测

1、下载yolov9的项目 地址:YOLOv9 2、使用下面代码进行检测 import torchimport cv2from models.experimental import attempt_loadfrom utils.general import non_max_suppression, scale_boxesfrom utils.plots import plot_o

如何给MySQL设置远程访问?(官方校正版)

在现代数据驱动的世界中,数据库的灵活性和可访问性变得尤为重要。设置MySQL的远程访问不仅仅是为了方便,还为企业和开发者提供了多种优势。无论是在分布式团队协作、跨地域数据管理,还是在系统集成和实时数据访问方面,远程访问都能显著提升效率和生产力。 目录 1. 修改MySQL配置文件 2. 重启MySQL服务 3. 创建远程访问用户 4. 配置防火墙 a. 使用UFW(适用于Ubun

使用Flink CDC实时监控MySQL数据库变更

在现代数据架构中,实时数据处理变得越来越重要。Flink CDC(Change Data Capture)是一种强大的工具,可以帮助我们实时捕获数据库的变更,并进行处理。本文将介绍如何使用Flink CDC从MySQL数据库中读取变更数据,并将其打印到控制台。 环境准备 <dependency><groupId>org.apache.flink</groupId><artifactId>

RTP:实时传输协议详解(转)

实时传输协议RTP 1.RTP协议: RTP( Real-time Transport Protocol)协议最初是在70年代为了尝试传输声音文件,把包分成几部分用来传输语音,时间标志和队列号。经过一系列发展,RTP第一版本在1991年8月由美国的一个实验室发布了。到本世纪1996年形成了标准的的版本。很多著名的公司如Netscape ,就宣称“Netscape LiveMedia”是基于RTP协

Selenium WebDriverWait和expected_conditions来定位实时更新的元素

WebDriverWait 是 Selenium WebDriver 的一个等待机制,用于等待一个特定条件成立直到一个最大的时间阈值。这种等待方式是显式等待,与隐式等待相对。显式等待提供了一种更灵活的方式来等待页面上的元素或条件,因为它允许你指定等待条件和时间。 WebDriverWait 通常与 expected_conditions 一起使用,来指定等待的条件。当条件满足时,等待操作会立即结

【GD32】从零开始学兆易创新32位微处理器——RTC实时时钟+日历例程

1 简介 RTC实时时钟顾名思义作用和墙上挂的时钟差不多,都是用于记录时间和日历,同时也有闹钟的功能。从硬件实现上来说,其实它就是一个特殊的计时器,它内部有一个32位的寄存器用于计时。RTC在低功耗应用中可以说相当重要,因为在使用外部低速晶振的条件下,它在所有的低功耗模式下都可以工作,这使得RTC很适合实现芯片的低功耗唤醒。下面是RTC的框图。 咋一看RTC的内部还挺复杂的。 2 硬件时

YOLOv9基础 | 实时目标检测新SOTA,手把手带你深度解析yolov9论文!

前言:Hello大家好,我是小哥谈。YOLOv9是Chien-Yao Wang等人提出的YOLO系列的最新版本之一(截止到目前,YOLOv10已发布),于2024年2月21日发布。它是 YOLOv7的改进版本,两者均由Chien-Yao Wang及其同事开发。本节课就以YOLOv9论文为基础带大家深入解析YOLOv9算法。🌈        目录 🚀1.算法介绍 🚀2.论文解析

STM32读写备份寄存器和实时时钟

文章目录 1. 硬件电路 2. RTC操作注意事项 操作步骤 3. 代码实现 3.1 读写备份寄存器 3.1.1 main.c 3.2 实时时钟 3.2.1 MyRTC.c 3.2.2 MyRTC.h 3.2.3 main.c 1. 硬件电路 对于BKP备份寄存器和RTC实时时钟的详细解析可以看下面这篇文章: STM32单片机BKP备份寄存器和RTC实时时钟详解

深交所互动易问答平台关键词实时监控提醒

首先打开深交所互动易问答平台网站,打开开发者工具,选择网络内容,然后在最新提问和最新答复来回点击,发现它通过另一个网址加载数据,我们直接找到这个网址,问题就简单多了。 在新的选项卡中打开最新提问内容的网址,再分析这个页面。分析提问内容和链接,其中链接包含“viewQuestionForSzse.do?questionid=”这样的字符串 在新的选项卡中,打开最