当前位置: 首页 > article >正文

计算机视觉——基于使用 OpenCV 与 Python 实现相机标定畸变校正

概述

相机标定是一种旨在通过确定相机的内参(焦距、光学中心、畸变系数)和外参(相机的位置和方向),提高图像在现实世界中的几何精度的过程。该过程可以纠正相机拍摄的图像中的畸变,使相机能够准确感知现实世界中的距离、角度和物体。一个很好的例子是纠正鱼眼相机拍摄的图像。

一、什么是相机标定

相机通过将其投影到二维平面上来捕捉现实世界。然而,由于光学元件和镜头的结构特性,这些图像可能会出现误差。最常见的误差是畸变和透视误差。相机标定通过计算相机的内参和外参来纠正这些误差,从而实现更准确的测量和几何计算。

关键参数

  1. 内参

    • 焦距:根据镜头的焦距确定图像的大小。
    • 光学中心(主点):相机镜头的中心点。
    • 畸变系数:用于纠正镜头畸变,如桶形畸变和枕形畸变。(你可以在图 1 中清楚地看到这一点。)

    注意:术语“畸变”指的是镜头引起的误差,如变形或弯曲。

    图 1. 枕形畸变和桶形畸变

  2. 外参

    • 相机位置:相机相对于世界的位置(x、y、z 坐标)。
    • 相机方向:相机相对于世界的视角(旋转角度)。

    图 2. 收集标定用的视觉数据

二、如何进行相机标定

通常使用已知的几何图案(如棋盘格)进行相机标定。该图案的已知尺寸和位置用作参考,以检测相机图像中的畸变。 标定过程包括以下步骤:

  1. 图像采集:要进行相机标定,你需要一组至少 15 张从不同角度拍摄的棋盘格图案的图像。该图案的角点有助于检测图像中的畸变。
  2. 角点检测:在每张图像中检测棋盘格图案的角点。正确检测这些角点对于准确标定至关重要。
  3. 内参和外参的计算:根据相机图像中的角点与它们的真实世界坐标之间的差异,优化并计算相机的内参和外参。通常使用 AI 算法或数学优化技术进行此计算。
  4. 畸变纠正:使用计算出的参数纠正图像中的畸变,去除非线性镜头畸变。
  5. 验证:为了测试标定的准确性,用相机拍摄一张新图像,并应用标定参数来纠正图像。然后观察纠正的准确性。

图 3. 添加桶形畸变
图 4. 标定结果示例

三、使用 OpenCV 在 Python 中进行相机标定

OpenCV 是 Python 中用于相机标定最常用的库之一。OpenCV 提供了相机标定和畸变纠正所需的函数。以下是简单的标定示例:

import cv2
import numpy as np
import glob# 棋盘格的尺寸(内部角点的数量)
grid_size = (9, 6)# 每个正方形的实际尺寸(2 厘米)
square_size = 2  # 厘米# 棋盘格的 3D 世界坐标
obj_points = np.zeros((grid_size[0] * grid_size[1], 3), np.float32)
obj_points[:, :2] = np.mgrid[0:grid_size[0], 0:grid_size[1]].T.reshape(-1, 2) * square_size# 用于存储标定所需点的列表
object_points = []  # 3D 世界坐标
image_points = []  # 2D 图像坐标# 存放标定图像的文件夹
images = glob.glob('calibration_images/*.jpg')for fname in images:img = cv2.imread(fname)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 查找棋盘格的角点ret, corners = cv2.findChessboardCorners(gray, grid_size, None)if ret:object_points.append(obj_points)image_points.append(corners)# 可视化角点cv2.drawChessboardCorners(img, grid_size, corners, ret)cv2.imshow('Chessboard Corners', img)cv2.waitKey(500)cv2.destroyAllWindows()# 执行标定
ret, camera_matrix, dist_coeffs, rvecs, tvecs = cv2.calibrateCamera(object_points, image_points, gray.shape[::-1], None, None
)# 保存相机矩阵和畸变系数
np.savez('calibration_data.npz', camera_matrix=camera_matrix, dist_coeffs=dist_coeffs)# 打印标定结果
print("Camera Matrix:\n", camera_matrix)
print("Distortion Coefficients:\n", dist_coeffs)

四、代码解释

import cv2
import numpy as np
import glob
  • cv2(OpenCV):我们导入 OpenCV,这是一个用于图像处理的库。该库提供了许多用于相机标定和图像处理的函数。
  • numpy(np):我们导入 NumPy,以便轻松进行数值运算和处理数组。
  • glob:用于组织文件路径并列出文件夹中的文件。在这里,它用于获取包含标定图像的文件夹中的所有图像。
grid_size = (9, 6)
  • grid_size:指定棋盘格上内部角点的数量。在此示例中,棋盘格图案有 9 列和 6 行角点(9 列 × 6 行 = 54 个角点)。此值应与实际使用的棋盘格匹配。
square_size = 2  # cm
  • square_size:棋盘格上的每个正方形的实际边长设置为 2 厘米。
obj_points = np.zeros((grid_size[0] * grid_size[1], 3), np.float32)
obj_points[:, :2] = np.mgrid[0:grid_size[0], 0:grid_size[1]].T.reshape(-1, 2) * square_size
  • obj_points:我们创建棋盘格角点在真实世界坐标中的 3D 位置。每个角点的 Z 轴值设置为 0。
  • np.zeros((grid_size[0] * grid_size[1], 3), np.float32):创建一个 3D 空矩阵,为每个角点包含(x、y、z)坐标。
  • np.mgrid[0:grid_size[0], 0:grid_size[1]]:生成棋盘格上角点的(x、y)坐标。

注意mgrid 是 NumPy 的一个函数,用于创建多维网格结构,其语法为 mgrid[start:end:step]

例如:

# 二维网格(网格)
x, y = np.mgrid[0:3, 0:3]
print("X:\n", x)
print("Y:\n", y)

输出:

X:[[0 0 0][1 1 1][2 2 2]]
Y:[[0 1 2][0 1 2][0 1 2]]
  • T.reshape(-1, 2):将二维角点转换为单个矩阵。
object_points = []  # 3D 世界坐标
image_points = []  # 2D 图像坐标
  • object_points:一个列表,用于存储每张图像的 3D 真实世界棋盘格角点。
  • image_points:一个列表,用于存储每张图像的 2D 图像角点。
images = glob.glob('calibration_images/*.jpg')
  • images:查找 calibration_images 文件夹中的所有 .jpg 文件,并将它们存储在一个列表中。这些是用于标定的棋盘格图案图像。
for fname in images:img = cv2.imread(fname)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  • 此循环处理每张图像:
    • cv2.imread(fname):读取由 fname 指定的图像。
    • cv2.cvtColor(img, cv2.COLOR_BGR2GRAY):将读取的图像从彩色(BGR)转换为灰度。在灰度图像上检测棋盘格图案更容易。
ret, corners = cv2.findChessboardCorners(gray, grid_size, None)
  • cv2.findChessboardCorners:尝试在灰度图像中查找棋盘格的角点。
  • ret:一个标志(True/False),指示是否成功找到棋盘格的角点。
  • corners:检测到的图像中角点的 2D 坐标。
if ret:object_points.append(obj_points)image_points.append(corners)
  • 如果 retTrue,即成功找到棋盘格的角点:
    • object_points.append(obj_points):将 3D 真实世界坐标添加到列表中。
    • image_points.append(corners):将 2D 图像坐标添加到列表中。
cv2.drawChessboardCorners(img, grid_size, corners, ret)
cv2.imshow('Chessboard Corners', img)
cv2.waitKey(500)
  • cv2.drawChessboardCorners:通过在图像上绘制线条来可视化检测到的棋盘格角点。
  • cv2.imshow:在一个新窗口中显示带有检测到的角点的图像。
  • cv2.waitKey(500):显示图像 500 毫秒(0.5 秒)。
cv2.destroyAllWindows()
  • cv2.destroyAllWindows:关闭所有打开的窗口。
ret, camera_matrix, dist_coeffs, rvecs, tvecs = cv2.calibrateCamera(object_points, image_points, gray.shape[::-1], None, None
)
  • camera_matrix:一个包含相机内参(焦距、光学中心等)的矩阵。
  • dist_coeffs:镜头畸变系数。
  • rvecs:旋转向量。
  • tvecs:平移向量。
  • cv2.calibrateCamera:执行相机标定。该函数根据真实世界 3D 点与其在图像中的对应 2D 点之间的关系计算相机参数。
  • object_points:3D 真实世界坐标。
  • image_points:图像中的 2D 投影坐标。
  • gray.shape[::-1]:图像分辨率(宽度和高度)。
  • camera_matrix(默认值:None)—— calibrateCamera 的参数:这是一个 3×3 矩阵,表示相机的内参(焦距、主点等)。如果提供为 None,这些参数将由函数计算。如果你有一个已知的相机矩阵,你可以在这里提供它。
  • dist_coeffs(默认值:None)—— calibrateCamera 的参数:这是一个表示畸变系数(畸变)的向量。如果提供为 None,畸变系数将由函数计算。

注意提供 **camera_matrix=None** **dist_coeffs=None** 的原因是你希望计算这些参数并获得标定的结果。 在你的代码中,你试图从特定图像中推导出相机的内参和镜头畸变系数(camera_matrix 和 dist_coeffs)。

  • flags(可选):这些是用于在标定期间指定某些选项的标志。例如:
    • cv2.CALIB_USE_INTRINSIC_GUESS:启用内参(相机矩阵和畸变系数)的初始猜测。
    • cv2.CALIB_FIX_PRINCIPAL_POINT:固定主点。
    • cv2.CALIB_FIX_ASPECT_RATIO:固定纵横比。
  • criteria(可选):指定迭代标准。这是优化过程的停止条件,通常与 cv2.TERM_CRITERIA_MAX_ITERcv2.TERM_CRITERIA_EPS 等选项一起使用。
np.savez('calibration_data.npz', camera_matrix=camera_matrix, dist_coeffs=dist_coeffs)
  • np.savez:将计算出的相机矩阵和畸变系数保存到名为 calibration_data.npz 的文件中。此文件允许你稍后重用标定参数。
print("Camera Matrix:\n", camera_matrix)
print("Distortion Coefficients:\n", dist_coeffs)
  • print:在屏幕上显示 camera_matrix(内参)和 dist_coeffs

此代码使用 OpenCV 进行相机标定,并保存结果。相机标定对于纠正图像中的畸变以及进行准确测量至关重要。

五、标定结果中你将获得的值

在这一过程结束时,camera_matrixdist_coeffs 将由函数计算并返回:

camera_matrix

该矩阵包含相机的内参(焦距、主点等)。它用于了解相机镜头的特性以及透视变换。它是一个 3×3 矩阵,可能如下所示:

camera_matrix 示例

在这里,f_xf_y 是相机沿水平和垂直方向的焦距(以像素为单位),c_xc_y 是图像平面上主点的像素坐标(通常是图像的中心)。

什么是主点? 主点表示图像的光学中心,并定义了相机镜头与图像平面之间的关系。如果相机的光轴偏离中心,这种偏移可以通过 c_xc_y 坐标检测到。

示例
假设你的相机分辨率为 1920×1080 像素,标定后你获得以下 camera_matrix:

camera_matrix 示例 2

  • f_x = 1200f_y = 1200:沿水平和垂直方向的焦距。
  • c_x = 960c_y = 540:主点的坐标,位于图像平面的中心(960 和 540 表示中心点,因为你的分辨率为 1920×1080)。

dist_coeffs

该向量包含镜头的畸变系数。这些系数用于纠正镜头的几何畸变(例如桶形畸变或枕形畸变)。

通常,该向量包含以下系数:

dist_coeffs 示例

这些系数:

  1. k_1、k_2、k_3:径向畸变系数。这些系数用于纠正桶形或枕形畸变。如果图像中的畸变随着距离中心的增加而变得更加明显,这就是径向畸变,k_1k_2k_3 用于纠正这种畸变。k_1 纠正靠近图像中心的畸变。k_2 纠正向图像边缘的较大畸变。k_3 对远离中心的点(尤其是边缘)进行微调,特别是对于边缘处的畸变。

    桶形畸变:一种向边缘膨胀的畸变。

    枕形畸变:一种向边缘收缩的畸变。

  2. p_1、p_2:切向畸变系数。当镜头与传感器未完美对齐时,会发生这种畸变。如果镜头未完美居中或存在轴向偏移,图像倾向于向边缘偏移。p_1p_2 用于纠正这种倾斜。p_1 纠正沿 x 轴(水平平面)的偏移或畸变。p_2 纠正沿 y 轴(垂直平面)的偏移或畸变。

    什么是径向畸变和切向畸变?

    径向畸变:这些畸变导致图像中的直线随着距离中心的增加而弯曲。k_1k_2k_3 用于纠正这些曲线。

    切向畸变:当镜头与传感器不完全垂直时发生,导致图像向边缘偏移。p_1p_2 用于纠正这些偏移。

  3. k_4、k_5、k_6(可选):高阶径向畸变系数。这些参数用于纠正更复杂的畸变,例如来自超广角镜头的畸变。它们通常不用于标准标定,但在需要更精确的校正时可以应用。

示例:

dist_coeffs = [0.1, -0.25, 0.001, 0.002, 0.03]
  • k_1 = 0.1k_2 = -0.25:用于纠正径向畸变的系数。
  • p_1 = 0.001p_2 = 0.002:用于纠正切向畸变的系数。
  • k_3 = 0.03:一个高阶径向畸变系数。

KP 的值越大,校正效果越强。随着它们的减小,校正效果减弱。

相关文章:

计算机视觉——基于使用 OpenCV 与 Python 实现相机标定畸变校正

概述 相机标定是一种旨在通过确定相机的内参(焦距、光学中心、畸变系数)和外参(相机的位置和方向),提高图像在现实世界中的几何精度的过程。该过程可以纠正相机拍摄的图像中的畸变,使相机能够准确感知现实…...

Python作业4 文本词云统计,生成词云

编写程序,统计两会政府工作报告热词频率,并生成词云。 2025两会政府工作报告 import jieba import wordcloud from collections import Counter import re# 读取文件 with open("gov.txt", "r", encoding"gbk") as f:t …...

Jenkins 2.492.2 LTS 重置管理员密码

文章目录 1. Jenkins 关闭用户认证2. jenkins 修改密码 如果忘记了 Jenkins 的管理员密码的话,也不用担心,只要你有权限访问 Jenkins 的根目录,就可以轻松地重置密码。 1. Jenkins 关闭用户认证 // 查看 jenkins 家目录(使用 doc…...

1. python开发小笔记

本文件记录一些实用的python小知识,会一直更新 1. import路径 1.1 python的import搜索路径可以用sys.path查看: import sys print(sys.path) 1.2 python的搜索目录有: 本脚本所在目录环境变量PYTHONPATH指定的目录标准库目录,通…...

【裁判文书网DES3数据解密】逆向分析

点击翻页,出现请求,可以看到请求参数有个ciphertext密文,响应数据也是密文 打上断点,点击翻页,断住 可以看到postData里面的ciphertext已经生成 往前跟栈,可以发现是var ciphertext cipher(); funct…...

探索 JavaScript 中的 Promise 高级用法与实战

在现代 Web 开发中,异步编程已成为不可或缺的一部分。JavaScript 作为 Web 开发的核心语言,提供了多种处理异步操作的方式,其中 Promise 对象因其简洁、强大的特性而备受青睐。本文将深入探讨 Promise 的高级用法,并结合实际案例&…...

【dify实战】agent结合deepseek实现基于自然语言的数据库问答、Echarts可视化展示、Excel报表下载

使用dify agent实现数据库智能问答,echarts可视化展示,excel报表下载 观看视频,您将学会 在dify下如何快速的构建一个agent,来完成数据分析工作;如何在AI的回复中展示可视化的图表;如何在AI 的回复中加入E…...

C++学习:六个月从基础到就业——面向对象编程:接口设计

C学习:六个月从基础到就业——面向对象编程:接口设计 本文是我C学习之旅系列的第十五篇技术文章,重点讨论在C中进行接口设计的原则、技术和最佳实践。查看完整系列目录了解更多内容。 引言 在面向对象的软件开发中,良好的接口设计…...

花园灌溉问题

#include <bits/stdc.h> using namespace std;// 设置最大行列数&#xff08;题目限制 n, m ≤ 100&#xff09; const int N 104;// 标记某个格子是否已经被水浇灌 bool used[N][N];// 队列&#xff0c;用于 BFS&#xff0c;存储当前水源的位置 queue<pair<int,i…...

《AI大模型应知应会100篇》第22篇:系统提示词(System Prompt)设计与优化

第22篇&#xff1a;系统提示词(System Prompt)设计与优化 摘要 在大语言模型&#xff08;LLM&#xff09;应用中&#xff0c;系统提示词&#xff08;System Prompt&#xff09;是控制模型行为的核心工具之一。它不仅定义了模型的身份、角色和行为规范&#xff0c;还直接影响输…...

Jsp技术入门指南【六】jsp脚本原理及隐式对象

Jsp技术入门指南【六】jsp脚本原理及隐式对象 前言一、JSP 脚本元素1.1 声明1.2 表达式1.3 脚本标签 二、JSP 的隐式对象是什么三、隐式对象详解outrequestsessionapplicationconfigexception 前言 在之前的博客中&#xff0c;我们已经介绍了JSP的环境搭建、编译文件查找以及生…...

transient关键字深度解析

Java transient 关键字深度解析 1. 核心概念 (1) 基本定义 作用:标记字段不参与序列化 适用场景: 敏感数据(如密码、密钥) 临时计算字段 依赖运行时环境的字段(如Thread对象) (2) 语法示例 java public class User implements Serializable {private String username…...

Jsp技术入门指南【五】详细讲解jsp结构页面

Jsp技术入门指南【五】详细讲解jsp结构页面 前言一、JSP页面的结构二、JSP页面的部件1. 指令&#xff08;核心控制部件&#xff09;2. 动作&#xff08;页面交互部件&#xff0c;了解即可&#xff09;3. 脚本&#xff08;Java逻辑嵌入部件&#xff09; 三、JSP指令详解1.1 JSP指…...

Beyond Compare 30天评估到期 解决方法

Beyond Compare 30天评估到期 解决方法 一、问题二、解决办法2.1 第一步&#xff1a;打开注册表2.2 第二步&#xff1a;删除cacheID 三、效果 一、问题 Beyond Compare提示评估到期&#xff0c;重装也无效&#xff0c;只需简单两步&#xff0c;轻轻松松出困境。 二、解决办法…...

探索蓝桥杯:嵌入式开发技巧分享与实践

在信息技术飞速发展的今天&#xff0c;嵌入式系统作为物联网和智能设备的核心技术之一&#xff0c;正扮演着愈发重要的角色。蓝桥杯作为国内知名的科技竞赛平台&#xff0c;为广大学生和科技爱好者提供了展示自己嵌入式开发能力的舞台。在这场竞赛中&#xff0c;参赛者不仅需要…...

Arduino无线体感机器手——问题汇总

文章不介绍具体参数&#xff0c;有需求可去网上搜索。 特别声明&#xff1a;不论年龄&#xff0c;不看学历。既然你对这个领域的东西感兴趣&#xff0c;就应该不断培养自己提出问题、思考问题、探索答案的能力。 提出问题&#xff1a;提出问题时&#xff0c;应说明是哪款产品&a…...

学习设计模式《一》——简单工厂

一、基础概念 1.1、接口 简单的说&#xff1a;接口是【用来实现类的行为定义、约束类的行为】&#xff08;即&#xff1a;定义可以做什么&#xff09;&#xff1b;接口可以包含【实例方法】、【属性】、【事件】、【索引器】或这四种成员类型的任意组合。 接口的优点&#xff1…...

python有序列表

您的代码整体结构良好&#xff0c;但存在一些关键错误和优化点。以下是对代码的详细评价及改进建议&#xff1a;---### 主要问题1. **add方法中的链表断裂问题**- **问题描述**&#xff1a;当向链表中间插入节点时&#xff0c;未正确设置新节点的next&#xff0c;导致后续节点丢…...

使用Lombok @Builder 收参报错提示没有无参构造方法的原因与解决办法

使用Lombok Builder 收参报错提示没有无参构造方法的原因与解决办法 类上加了Builder之后接口接收前端传来的参数报错&#xff1a;(no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator) 1.解决办法…...

010数论——算法备赛

数论 模运算 一般求余都是对正整数的操作&#xff0c;如果对负数&#xff0c;不同编程语言结果可能不同。 C/javapythona>m,0<a%m<m-1 a<m,a%ma~5%32~-5%3 -21(-5)%(-3) -2~5%(-3)2-1正数&#xff1a;&#xff08;ab&#xff09;%m((a%m)(b%m))%m~正数&#xff…...

NAT、代理服务、内网穿透

NAT、代理服务、内网穿透 1、NAT1.1、NAT过程1.2、NAPT2、内网穿透3、内网打洞3、代理服务器3.1、正向代理3.2、反向代理1、NAT 1.1、NAT过程 之前我们讨论了IPv4协议中IP地址数量不充足的问题。NAT技术是当前解决IP地址不够用的主要手段,是路由器的一个重要功能。 NAT能够将…...

C# 点击导入,将需要的参数传递到弹窗的页面

点击导入按钮&#xff0c;获取本页面的datagridview标题的结构&#xff0c;并传递到导入界面。 新增一个datatable用于存储datagridview的caption和name&#xff0c;这里用的是devexpress组件中的gridview。 DataTable dt new DataTable(); DataColumn CAPTION …...

Linux 文件查找终极指南:find, locate, grep 等命令详解

在 Linux 系统管理和日常使用中,文件查找是一项不可或缺的基本技能。无论是寻找配置文件、查找日志文件中的特定错误,还是清理旧的临时文件,掌握高效的文件查找工具都能让你事半功倍。Linux 提供了多种强大的命令行工具来满足不同的查找需求。本文将详细介绍几个最常用、最强…...

嵌入式硬件常用总线接口知识体系总结和对比

0.前言 在嵌入式工程实现中,多多少少我们都使用过总线,各种各样的总线应用于不同场合,不同场景有不同的优势,但是我们在作为工程师过程中在如何选择项目合适的总线,根据什么来选?需要我们对项目全局和总线特征有所了解,本文目的就是对比多种总线的关键特征 我们在聊到…...

【unity实战】Unity动画层级(Animation Layer)的Sync同步和Timing定时参数使用介绍,同步动画层制作角色的受伤状态

文章目录 前言方案一&#xff1a;复制粘贴原有层级的状态机1、实现2、问题 方法二&#xff1a;勾选Sync同步动画层1、简单实现同步2、同步blend tree的问题3、动画状态的播放时长4、下层状态覆盖了上层状态 专栏推荐完结 前言 如何制作角色的受伤状态&#xff1f; 玩家角色在…...

Uniapp调用native.js使用经典蓝牙串口通讯方法及问题解决

本人尝试在uniapp环境下开发一款安卓应用&#xff0c;需要与使用经典蓝牙协议的设备进行串口通讯&#xff0c;而uniapp官方给出的蓝牙操作接口目前只支持BLE&#xff08;低功耗蓝牙&#xff09;&#xff0c;用该接口无法正常获取到我想要连接的设备。 通过大量搜索&#xff0c…...

C++23 新特性:行拼接前去除空白符 (P2223R2)

文章目录 1\. 什么是行拼接前去除空白符2\. 为什么需要这一特性3\. 示例代码输出结果 4\. 编译器支持5\. 优势与应用场景5.1 提高代码可读性5.2 减少潜在错误5.3 适用于多行字符串 6\. 其他相关特性7\. 总结 C 语言一直在不断进化&#xff0c;以满足现代软件开发的需求。C23 标…...

Windows 11设置开机自动运行 .jar 文件

Windows 11设置开机自动运行 .jar 文件 打开启动文件夹&#xff1a; 按下 Win R&#xff0c;输入 shell:startup&#xff0c;回车。 此路径为当前用户的启动文件夹&#xff1a; C:\Users\<用户名>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup创…...

【通过Zadig给鼠标适配器安装驱动后,鼠标动不了,无法恢复的解决办法】

【通过Zadig给鼠标适配器安装驱动后,鼠标动不了,无法恢复的解决办法 问题产生缘由感谢这位大佬提供的解决办法解决办法 问题产生缘由 通过Zadig给鼠标适配器安装USB GAMING MOUSE这个驱动后,鼠标动不了,无法恢复(重启电脑,卸载鼠标驱动再重装也不可以), 不过还好,我用的是笔记…...

GoogleCodeUtil.java

Google动态验证码实现 GoogleCodeUtil.java package zwf;import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.security.SecureRandom;/** https://mvnrepository.com/artifact/commons-codec/…...