CenterOS 6.5 安装Python3

由于Python2的支持即将结束,文章详细介绍了如何在CentOS 6.5系统上编译安装Python3.9,包括升级yum库,安装依赖如openssl 1.1.1,以及安装mysqlclient和M2Crypto库的过程。过程中提到了解决版本不兼容和依赖问题的方法。

:升级背景

服务器:CenterOS 6.5
Python安装版本: 3.9.13

因为Python2逐渐不被支持了,公司项目需要升级到Python3。因为服务器一直在运行,系统整体升级风险比较大,故直接在原系统升级python2.7到python3.9


:Python3编译安装

python3.9编译依赖 openssl 1.1.1,lib-ffi, libffi-devel ,zlib, zlib-dev, bzip2-devel。除了openssl 1.1.1,其他通过yum安装即可

:yum配置更新

因为CenterOS6.5已经停止更新了,有些yum的库失效了,需要重新更新下yum库。

wget http://file.kangle.odata.cc/repo/Centos-6.repo     
wget http://file.kangle.odata.cc/repo/epel-6.repo  
/bin/cp -f Centos-6.repo /etc/yum.repos.d/CentOS-Base.repo
/bin/cp -f epel-6.repo /etc/yum.repos.d/epel.repo
yum makecache

:yum安装依赖库

更新完就可以安装需要的库了。

yum install -y libffi libffi-devel  
yum install -y zlib zlib-dev 
yum install -y bzip2-devel 

:安装openssl 1.1.1

从官网下载 openssl-1.1.1p.tar.gz

tar vxf openssl-1.1.1p.tar.gz
cd openssl-1.1.1p
./config shared zlib
make 
make install
rm -rf /usr/lib64/libssl.so
rm -rf /usr/lib64/libcrypto.so
ln -s /usr/local/lib64/libssl.so.1.1 /usr/lib64/libssl.so
ln -s /usr/local/lib64/libcrypto.so.1.1 /usr/lib64/libcrypto.so

注意,有些系统ssl的链接路径不在/usr/lib64下,在/lib64下,则需要链接对应的路径如下

rm -rf /lib64/libssl.so
rm -rf /lib64/libcrypto.so
ln -s /usr/local/lib64/libssl.so.1.1 /lib64/libssl.so
ln -s /usr/local/lib64/libcrypto.so.1.1 /lib64/libcrypto.so

:编译安装Python3

从官网下载Python-3.9.13.tgz,解压编译如下。因为openssl安装在/usr/local目录下,需要知道头文件位置

gunzip Python-3.9.13.tgz         
tar vxf Python-3.9.13.tar
cd Python-3.9.13
./configure --with-openssl=/usr/local --enable-optimizations
make
make install

:测试是否安装成功

[root@iZ28fsvqne3Z appserver]# python3
Python 3.9.13 (main, Jun 22 2022, 11:11:53)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-3)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import ssl
>>> ssl
<module 'ssl' from '/usr/local/lib/python3.9/ssl.py'>
>>> 

:mysqlclient库安装

centeros下mysql版本比较低,所以只能安装mysqlclient 1.4.4版本,否则编译会出错

yum install -y mysql-devel
pip3 install mysqlclient==1.4.4

:M2Crypto库安装

M2Crypto库安装依赖g++以及swig,所以需要升级对应的软件到指定版本

:升级swig到最新版本

如果M2Crypto安装出现 “–builtin” 选项找不到,表示swig版本太旧了,需要升级。

tar vxzf swig-3.0.7.tar.gz    
cd swig-3.0.7
./configure
make 
make install

:安装g++

g++依赖于libgcc,两者版本比较保持一致,否则无法安装。目前centeros 6.5下的gcc,g++版本是4.4.7-23,所以都升级到这个版本。

yum upgrade -y libgcc
yum upgrade -y libstdc++ 
yum install -y libstdc++-devel

gcc升级可能会出现循环依赖,则需要单独下载rpm包一块儿安装

rpm -i --replacefiles gcc-4.4.7-23.el6.x86_64.rpm libgomp-4.4.7-23.el6.x86_64.rpm cpp-4.4.7-23.el6.x86_64.rpm   

最后安装 g++

yum install -y gcc-c++   

:安装M2Crypto

pip3 install M2Crypto
import cv2 import numpy as np import json import os from scipy.spatial import distance import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D def load_camera_params(config_path):     """从配置文件加载相机参数"""     with open(config_path, &#39;r&#39;) as f:         config = json.load(f)     return config def project_3d_to_2d(point_3d, camera_matrix, dist_coeffs=None, rvec=None, tvec=None):     """     将3D坐标投影到2D图像上     :param point_3d: 3D坐标 (X, Y, Z)     :param camera_matrix: 相机内参矩阵 [[fx, 0, cx], [0, fy, cy], [0, 0, 1]]     :param dist_coeffs: 畸变系数 (k1, k2, p1, p2, k3)     :param rvec: 旋转向量     :param tvec: 平移向量     :return: 2D图像坐标 (u, v)     """     if dist_coeffs is None:         dist_coeffs = np.zeros(5, dtype=np.float32)     if rvec is None:         rvec = np.zeros(3, dtype=np.float32)     if tvec is None:         tvec = np.zeros(3, dtype=np.float32)     # 将3D点转换为numpy数组     point = np.array([point_3d], dtype=np.float32)     # 投影3D点到2D     projected, _ = cv2.projectPoints(         point, rvec, tvec, camera_matrix, dist_coeffs     )     return tuple(map(int, projected[0][0])) def draw_3d_bbox(image, center_3d, size, camera_matrix, dist_coeffs=None, rvec=None, tvec=None, color=(0, 255, 0), thickness=2):     """     在图像上绘制车辆的3D边界框     :param center_3d: 车辆中心3D坐标     :param size: 车辆尺寸 (长, 宽, 高)     :param color: 框线颜色 (B, G, R)     :param thickness: 线宽     """     l, w, h = size     half_l, half_w, half_h = l/2, w/2, h/2     # 生成3D边界框的8个角点     corners_3d = [         [center_3d[0] - half_l, center_3d[1] - half_w, center_3d[2] - half_h],         [center_3d[0] + half_l, center_3d[1] - half_w, center_3d[2] - half_h],         [center_3d[0] + half_l, center_3d[1] + half_w, center_3d[2] - half_h],         [center_3d[0] - half_l, center_3d[1] + half_w, center_3d[2] - half_h],         [center_3d[0] - half_l, center_3d[1] - half_w, center_3d[2] + half_h],         [center_3d[0] + half_l, center_3d[1] - half_w, center_3d[2] + half_h],         [center_3d[0] + half_l, center_3d[1] + half_w, center_3d[2] + half_h],         [center_3d[0] - half_l, center_3d[1] + half_w, center_3d[2] + half_h]     ]     # 投影角点到2D     corners_2d = [project_3d_to_2d(pt, camera_matrix, dist_coeffs, rvec, tvec) for pt in corners_3d]     # 绘制底部矩形     for i in range(4):         cv2.line(image, corners_2d[i], corners_2d[(i+1)%4], color, thickness)     # 绘制顶部矩形     for i in range(4):         cv2.line(image, corners_2d[i+4], corners_2d[4+(i+1)%4], color, thickness)     # 绘制垂直线     for i in range(4):         cv2.line(image, corners_2d[i], corners_2d[i+4], color, thickness)     # 绘制中心点     center_2d = project_3d_to_2d(center_3d, camera_matrix, dist_coeffs, rvec, tvec)     cv2.circle(image, center_2d, 5, (0, 0, 255), -1)     return center_2d def draw_distance(image, point1, point2, distance_3d, color=(0, 255, 255), thickness=2):     """     在图像上绘制两点之间的距离     :param point1: 第一个点的2D坐标     :param point2: 第二个点的2D坐标     :param distance_3d: 3D空间中的实际距离     :param color: 线条颜色     """     # 绘制连接线     cv2.line(image, point1, point2, color, thickness)     # 计算中点位置     mid_point = ((point1[0] + point2[0]) // 2, (point1[1] + point2[1]) // 2)     # 绘制距离标签     distance_text = f"{distance_3d:.2f}m"     cv2.putText(image, distance_text, mid_point,                cv2.FONT_HERSHEY_SIMPLEX, 0.7, color, 2)     # 绘制端点标记     cv2.circle(image, point1, 8, color, -1)     cv2.circle(image, point2, 8, color, -1) def visualize_3d_scene(vehicles_3d, camera_position, connections=None):     """     可视化3D场景     :param vehicles_3d: 车辆3D坐标列表     :param camera_position: 相机位置     :param connections: 需要连接的车辆对     """     fig = plt.figure(figsize=(12, 8))     ax = fig.add_subplot(111, projection=&#39;3d&#39;)     # 绘制车辆位置     for i, (x, y, z) in enumerate(vehicles_3d):         ax.scatter(x, y, z, c=&#39;b&#39;, s=100)         ax.text(x, y, z, f&#39;V{i+1}&#39;, size=12)     # 绘制相机位置     cx, cy, cz = camera_position     ax.scatter(cx, cy, cz, c=&#39;r&#39;, s=150, marker=&#39;s&#39;)     ax.text(cx, cy, cz, &#39;Camera&#39;, size=12)     # 绘制连接线     if connections:         for (i, j) in connections:             x1, y1, z1 = vehicles_3d[i]             x2, y2, z2 = vehicles_3d[j]             ax.plot([x1, x2], [y1, y2], [z1, z2], &#39;g-&#39;, linewidth=2)     # 设置坐标轴标签     ax.set_xlabel(&#39;X (m)&#39;)     ax.set_ylabel(&#39;Y (m)&#39;)     ax.set_zlabel(&#39;Z (m)&#39;)     ax.set_title(&#39;3D Vehicle Positions&#39;)     plt.tight_layout()     plt.show() def main(image_path, vehicles, camera_params, output_path=None):     """     主处理函数     :param image_path: 输入图像路径     :param vehicles: 车辆列表,每个元素为字典 {&#39;id&#39;: int, &#39;coords&#39;: [x, y, z]}     :param camera_params: 相机参数字典     :param output_path: 输出图像路径     """     # 加载图像     image = cv2.imread(image_path)     if image is None:         print(f"错误: 无法加载图像 {image_path}")         return     # 提取相机参数     camera_matrix = np.array(camera_params[&#39;intrinsic&#39;])     dist_coeffs = np.array(camera_params[&#39;distortion&#39;]) if &#39;distortion&#39; in camera_params else None     rvec = np.array(camera_params[&#39;rotation&#39;]) if &#39;rotation&#39; in camera_params else None     tvec = np.array(camera_params[&#39;translation&#39;]) if &#39;translation&#39; in camera_params else None     # 标准车辆尺寸 (长, 宽, 高) 单位:米     vehicle_size = [4.5, 1.8, 1.5]     # 获取车辆3D坐标     vehicle_coords = [v[&#39;coords&#39;] for v in vehicles]     vehicle_ids = [v[&#39;id&#39;] for v in vehicles]     # 绘制每辆车的3D边界框     centers_2d = []     for coords in vehicle_coords:         center_2d = draw_3d_bbox(image, coords, vehicle_size, camera_matrix, dist_coeffs, rvec, tvec)         centers_2d.append(center_2d)     # 计算并标注车辆之间的距离     connections = []     for i in range(len(vehicle_coords)):         for j in range(i+1, len(vehicle_coords)):             # 计算3D欧几里得距离             dist = distance.euclidean(vehicle_coords[i], vehicle_coords[j])             # 绘制距离标注 (只绘制近距离的车辆对)             if dist < 20: # 只标注20米内的车辆                 draw_distance(image, centers_2d[i], centers_2d[j], dist)                 connections.append((i, j))     # 添加图像标题     cv2.putText(image, "Vehicle Distance Visualization", (20, 40),                cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 0, 255), 3)     # 显示或保存结果     if output_path:         cv2.imwrite(output_path, image)         print(f"结果已保存至: {output_path}")     # 显示结果图像     cv2.imshow("Vehicle Projection and Distance", image)     cv2.waitKey(0)     cv2.destroyAllWindows()     # 可视化3D场景     camera_position = tvec if tvec is not None else [0, 0, 0]     visualize_3d_scene(vehicle_coords, camera_position, connections) def process_from_json(json_file):     """     从JSON文件加载数据并处理     :param json_file: JSON文件路径     """     with open(json_file, &#39;r&#39;) as f:         data = json.load(f)     # 提取必要数据     image_path = data[&#39;image_path&#39;]     vehicles = data[&#39;vehicles&#39;]     # 相机参数 (这里使用示例参数,实际应从配置文件或元数据获取)     camera_params = {         &#39;intrinsic&#39;: [[1000, 0, 640], [0, 1000, 360], [0, 0, 1]], # 内参矩阵         &#39;distortion&#39;: [0.1, -0.05, 0, 0, 0], # 畸变系数         &#39;rotation&#39;: [0, 0, 0], # 旋转向量         &#39;translation&#39;: [0, 0, 0] # 平移向量     }     # 输出路径     output_dir = os.path.dirname(image_path)     output_name = os.path.splitext(os.path.basename(image_path))[0] + &#39;_annotated.jpg&#39;     output_path = os.path.join(output_dir, output_name)     # 处理图像     main(image_path, vehicles, camera_params, output_path) # 使用示例 if __name__ == "__main__":     # 示例1: 直接使用参数调用     image_path = "path/to/your/image.jpg"     # 车辆3D坐标 (相机坐标系)     vehicles = [         {"id": 1, "coords": [8.2, -1.2, 15.5]},         {"id": 2, "coords": [6.5, 1.8, 12.3]},         {"id": 3, "coords": [10.5, -2.1, 18.7]}     ]     # 相机参数 (需要根据实际相机校准)     camera_params = {         &#39;intrinsic&#39;: [[1200, 0, 960], [0, 1200, 540], [0, 0, 1]], # 内参矩阵 &#39;distortion&#39;: [0.1, -0.05, 0, 0, 0], # 畸变系数 &#39;rotation&#39;: [0, 0, 0], # 旋转向量 &#39;translation&#39;: [0, 0, 0] # 平移向量 } # 处理图像 main(image_path, vehicles, camera_params, "output_image.jpg") # 示例2: 从JSON文件处理 # process_from_json("image_data.json")
最新发布
07-22
<think>我们有一个用于在图像上绘制车辆3D边界框并计算车辆间距离的Python程序。该程序使用OpenCV和Matplotlib进行图像处理和3D可视化。 主要功能: 1. 从配置文件加载相机参数。 2.3D点投影到2D图像上。 3. 在图像上绘制车辆的3D边界框(长方体)。 4. 在图像上标注车辆之间的距离(仅当距离小于20米时)。 5. 使用Matplotlib可视化3D场景(车辆位置和相机位置)。 程序结构: - load_camera_params: 从JSON文件加载相机参数。 - project_3d_to_2d: 将3D点投影到2D图像坐标。 - draw_3d_bbox: 在图像上绘制车辆的3D边界框。 - draw_distance: 在图像上绘制两点之间的距离,并标注距离值。 - visualize_3d_scene: 使用Matplotlib绘制3D场景。 - main: 主函数,处理图像并绘制结果。 - process_from_json: 从JSON文件加载数据并调用主函数处理。 示例使用: 1. 直接调用main函数,传入图像路径、车辆列表(包含id和3D坐标)和相机参数。 2. 通过process_from_json函数,从JSON文件加载数据。 注意: 相机坐标系:通常,在相机坐标系中,X轴向右,Y轴向下,Z轴向前(指向场景)。 车辆3D坐标:在相机坐标系中的位置(单位:米)。 车辆尺寸:使用固定尺寸(长4.5米,宽1.8米,高1.5米)绘制边界框。 代码中可能存在的问题: 1. 在投影函数中,如果旋转向量(rvec)和平移向量(tvec)为None,则使用零向量。但实际中,相机可能不在原点,需要根据实际情况设置。 2. 在绘制3D边界框时,假设车辆中心在3D坐标点,并且边界框是轴对齐的(没有考虑车辆方向)。实际中,车辆可能有朝向,但这里简化了。 3. 相机参数需要根据实际相机校准得到,示例中的参数是假设的。 改进建议: 1. 考虑车辆的朝向(偏航角)来绘制更准确的3D边界框。 2. 相机的外参(旋转和平移)通常表示从世界坐标系到相机坐标系的变换,这里车辆坐标已经是相机坐标系,所以外参可以忽略(即rvec和tvec为零)。但如果有世界坐标系,则需要先转换到相机坐标系。 现在,我们将按照要求,对代码进行解释,并给出相关问题的解答。 注意:由于代码较长,我们不会重写整个代码,而是对关键部分进行解释。 代码解释: 1. 投影3D点到2D: 使用OpenCV的cv2.projectPoints函数。该函数需要3D点(相对于相机坐标系),旋转向量(如果3D点已经在相机坐标系,则旋转向量可以为零),平移向量(同理为零),相机内参矩阵和畸变系数。 2. 绘制3D边界框: 根据车辆中心位置和尺寸(长、宽、高)计算8个角点,然后投影到2D,绘制12条边(底部4条,顶部4条,连接底部和顶部的4条)。 3. 绘制距离: 计算两个车辆中心点的3D欧氏距离,然后在图像上绘制两个中心点的连线,并在中点标注距离。 4. 3D场景可视化: 使用Matplotlib的3D绘图功能,将车辆位置和相机位置在3D坐标系中显示,并连接需要显示距离的车辆对。 示例运行: 在__main__中提供了两种调用方式:直接调用main和通过JSON文件调用。 相关问题: 根据要求,我们需要在最后提出4个相关问题。 注意:由于代码已经给出,我们只解释和提供相关问题的解答。</think>### 代码分析与解释 您提供的代码实现了一个完整的车辆3D检测与可视化系统,主要功能包括: 1.3D坐标投影到2D图像 2. 在图像上绘制车辆的3D边界框 3. 计算并标注车辆间的3D距离 4. 生成3D场景可视化 以下是关键函数的详细解释: --- #### 1. 相机参数加载 (`load_camera_params`) ```python def load_camera_params(config_path): with open(config_path, &#39;r&#39;) as f: config = json.load(f) return config ``` - **功能**:从JSON文件加载相机内参、畸变系数和外参 - **关键参数**: - `intrinsic`:相机内参矩阵 `[fx, fy, cx, cy]` - `distortion`:径向和切向畸变系数 - `rotation`:旋转向量(罗德里格斯表示) - `translation`:平移向量 --- #### 2. 3D到2D投影 (`project_3d_to_2d`) ```python def project_3d_to_2d(point_3d, camera_matrix, dist_coeffs=None, rvec=None, tvec=None): # ... (参数检查) projected, _ = cv2.projectPoints( point, rvec, tvec, camera_matrix, dist_coeffs ) return tuple(map(int, projected[0][0])) ``` - **核心函数**:`cv2.projectPoints` - **数学原理**: ``` [u] [fx 0 cx] [X/Z] [v] = [0 fy cy] * [Y/Z] [1] [0 0 1] [ 1 ] ``` - **处理流程**: 1.3D点转换为齐次坐标 2. 应用相机内参矩阵 3. 应用畸变校正模型: ```math x&#39; = x(1 + k_1 r^2 + k_2 r^4 + k_3 r^6) + 2p_1xy + p_2(r^2+2x^2) ``` --- #### 3. 3D边界框绘制 (`draw_3d_bbox`) ```python def draw_3d_bbox(image, center_3d, size, camera_matrix, ...): l, w, h = size half_l, half_w, half_h = l/2, w/2, h/2 # 计算8个角点 corners_3d = [ [center_3d[0]-half_l, center_3d[1]-half_w, center_3d[2]-half_h], ... # 7个其他角点 ] # 投影到2D并绘制12条边 corners_2d = [project_3d_to_2d(...) for pt in corners_3d] for i in range(4): cv2.line(image, corners_2d[i], corners_2d[(i+1)%4], color, thickness) ... # 绘制顶部和垂直线 ``` - **关键步骤**: 1. 根据车辆中心点和尺寸计算8个边界角点 2. 将所有角点投影到2D图像平面 3. 绘制: - 底部四边形(索引0-3) - 顶部四边形(索引4-7) - 连接顶部和底部的4条垂直线 --- #### 4. 距离标注 (`draw_distance`) ```python def draw_distance(image, point1, point2, distance_3d, ...): cv2.line(image, point1, point2, color, thickness) mid_point = ((point1[0]+point2[0])//2, (point1[1]+point2[1])//2) cv2.putText(image, f"{distance_3d:.2f}m", mid_point, ...) ``` - **功能**:在两点连线的中点显示3D距离 - **距离计算**:使用欧几里得距离 `sqrt((x1-x2)^2 + (y1-y2)^2 + (z1-z2)^2)` --- #### 5. 3D场景可视化 (`visualize_3d_scene`) ```python def visualize_3d_scene(vehicles_3d, camera_position, connections): fig = plt.figure() ax = fig.add_subplot(111, projection=&#39;3d&#39;) # 绘制车辆和相机 for i, (x,y,z) in enumerate(vehicles_3d): ax.scatter(x, y, z, c=&#39;b&#39;, s=100) # 绘制连接线 for (i,j) in connections: ax.plot([x1,x2], [y1,y2], [z1,z2], &#39;g-&#39;) ``` - **依赖库**:`matplotlib`的3D绘图工具包 - **可视化元素**: - 蓝色圆点:车辆位置 - 红色方块:相机位置 - 绿色连线:车辆间距离关系 --- ### 改进建议与注意事项 1. **车辆朝向处理**: ```python # 改进建议:增加旋转角度参数 def draw_3d_bbox(..., yaw_angle=0): # 根据yaw旋转角点 rotation_matrix = cv2.Rodrigues(np.array([0, yaw_angle, 0]))[0] rotated_corners = [rotation_matrix @ corner for corner in local_corners] ``` 2. **相机坐标系假设**: - 当前代码假设3D坐标在**相机坐标系**中 - 若使用世界坐标,需先转换: ```python camera_coords = R @ world_coords + T ``` 3. **性能优化**: ```python # 批量投影替代循环 all_points = np.array(corners_3d, dtype=np.float32) projected, _ = cv2.projectPoints(all_points, ...) ``` 4. **错误处理**: ```python # 添加投影有效性检查 if any(not (0 <= u < width and 0 <= v < height) for u,v in corners_2d): print("警告:部分角点超出图像边界") ``` --- ### 示例调用流程 ```python # 1. 定义车辆信息 vehicles = [ {"id": 1, "coords": [8.2, -1.2, 15.5]}, {"id": 2, "coords": [6.5, 1.8, 12.3]} ] # 2. 配置相机参数 camera_params = { &#39;intrinsic&#39;: [[1200,0,960], [0,1200,540], [0,0,1]], &#39;distortion&#39;: [0.1,-0.05,0,0,0], &#39;rotation&#39;: [0,0,0], &#39;translation&#39;: [0,0,0] } # 3. 处理图像 main("traffic.jpg", vehicles, camera_params, "output.jpg") ```
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值