前言
仅记录学习过程,有问题欢迎讨论
立体视觉--(自动驾驶)::
目的是从多幅图像中推理出图像中像素点的深度信息
原理 :理由左右眼的差异,识别出物体的远近(视差)
单目系统 :无法区分远近,多个相同位置物体识别为一个像素点
双目系统 :根据左右眼视差,根据相似原理,计算物体距离(视差)
视差:同一空间物理点在不同图像中的映像点对应起来就是视差
点云模型:三维转二维
点云:激光测量扫描资料以点的形式记录,每一个点包含有三维坐标,有些含有颜色或反射强度信息
点云处理的三个层次:
-
低层次处理:高斯滤波,双边滤波,条件滤波,直通滤波 SIFT3D
-
中层次处理方法:
①特征描述:法线和曲率的计算、特征值分析、Spin Image
②分割与分类:
分割:区域生长、Ransac线面提取、全局优化平面提取 K-Means、3D Hough Transform(线、面提取)、连通分析
分类:基于点的分类,基于分割的分类,基于深度学习的分类
-
高层次处理方法:
1、配准:点云配准分为粗配准和精配准两个阶段。
精配准的目的是在粗配准的基础上让点云之间的空间位置差别最小化。
粗配准是指在点云相对位姿完全未知的情况下对点云进行配准,可以为精配准提供良好的初始值。
2、SLAM图优化
Ceres(Google的最小二乘优化库,很强大), g2o、LUM、ELCH、Toro、SPA
SLAM方法:ICP、MBICP、IDC、likehood Field、NDT
3、三维重建
泊松重建、 Delaunay triangulations、表面重建,人体重建,建筑物重建,树木重建。
实时重建:重建植被或者农作物的4D(3D+时间)生长态势;人体姿势识别;表情识别;
4、点云数据管理:点云压缩,点云索引(KD、Octree),点云LOD(金字塔),海量点云的渲染
SPIN IMAGE(实现3D转2D):
- 定义一个Oriented point
- 以Oriented point为轴生成一个圆柱坐标系
- 定义Spin image的参数,Spin image是一个具有一定大小(行数列数)、分辨率(二维网格大小)的二维图像,
super angle(所选点和定点法向量夹角的大小限制,切面的"凹点"(大于【60-90】°)"被剔除)。 - 将圆柱体内的三维坐标投影到二维Spin image,这一过程可以理解为一个Spin image绕着法向量n旋转360度,
Spin image扫到的三维空间的点会落到Spin image的网格中(旋转门)。 - 根据spin image中的每个网格中落入的点不同,计算每个网格的强度,当一个点落入网格(i,j)中时会被双线性插值分散到4个网格中
分类和聚类:
聚类通常是无标签的,属于无监督学习
在图像处理中,通过K-Means (常用)聚类算法可以实现图像分割、图像聚类、图像识别等操作。
我们通过K-Means可以将这些像素点聚类成K个簇,然后使用每个簇内的质心点来替换簇内所有
的像素点,这样就能实现在不改变分辨率的情况下量化压缩图像颜色,实现图像颜色层级分割。
层次聚类和密度聚类:
层次聚类:自底向上的策略,将每个样本点作为一个簇,然后根据距离合并,直到达到预设的簇的数量
缺点:计算复杂度太高;算法很可能聚类成链状
密度聚类:基于密度的聚类,从密度高的区域开始,不断向外扩展,直到密度过低,停止扩展
缺点:聚类的结果与参数有很大的关系;优点对噪声不敏感
Canny算法和透视变化
py
"""
k-means
第一步,确定K值,即将数据集聚集成K个类簇或小组。
----这里我们选K=2
第二步,从数据集中随机选择K个数据点作为质心(Centroid)或数
据中心。
----假设我们选择P1和P2作为初始的质心
第三步,分别计算每个点到每个质心之间的距离,并将每个点划分
到离最近质心的小组。
----计算P3到P1的距离:√10 = 3.16;
----计算P3到P2的距离:√((3-1)^2+(1-2)^2 = √5 = 2.24;
----所以P3离P2更近,P3就加入P2的簇。同理,P4、P5、P6;
"""
# 实现kmeans
import random
import sys
import numpy as np
class KMeansClusterer: # k均值聚类
def __init__(self, ndarray, cluster_num):
self.ndarray = ndarray
self.cluster_num = cluster_num
self.points = self.__pick_start_point(ndarray, cluster_num)
def cluster(self):
result = []
for i in range(self.cluster_num):
result.append([])
for item in self.ndarray:
distance_min = sys.maxsize
index = -1
for i in range(len(self.points)):
distance = self.__distance(item, self.points[i])
if distance < distance_min:
distance_min = distance
index = i
result[index] = result[index] + [item.tolist()]
new_center = []
for item in result:
new_center.append(self.__center(item).tolist())
# 中心点未改变,说明达到稳态,结束递归
if (self.points == new_center).all():
sum = self.__sumdis(result)
return result, self.points, sum
self.points = np.array(new_center)
return self.cluster()
def __sumdis(self, result):
# 计算总距离和
sum = 0
for i in range(len(self.points)):
for j in range(len(result[i])):
sum += self.__distance(result[i][j], self.points[i])
return sum
def __center(self, list):
# 计算每一列的平均值
return np.array(list).mean(axis=0)
def __distance(self, p1, p2):
# 计算两点间距
tmp = 0
for i in range(len(p1)):
tmp += pow(p1[i] - p2[i], 2)
return pow(tmp, 0.5)
def __pick_start_point(self, ndarray, cluster_num):
if cluster_num < 0 or cluster_num > ndarray.shape[0]:
raise Exception("簇数设置有误")
# 取点的下标
indexes = random.sample(np.arange(0, ndarray.shape[0], step=1).tolist(), cluster_num)
points = []
for index in indexes:
points.append(ndarray[index].tolist())
return np.array(points)
x = np.random.rand(100, 8)
kmeans = KMeansClusterer(x, 10)
result, centers, distances = kmeans.cluster()
print(result)
print(centers)
print(distances)