为啥不同的手机定位有误差。
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为啥不同的手机定位有误差。相关的知识,希望对你有一定的参考价值。
您好!很高兴能为您解答,
手机定位原理
要搞清定位偏差的问题,还得先理解手机定位的原理。目前主流的手机定位方式可以分为三类: GPS定位、 基站定位、 混合定位。
GPS定位是通过手机中GPS模块获取位置信息,理论上民用GPS定位可以实现5米内误差,也是最为精准的方式。
基站定位是依靠运营商的电信基站进行定位,由于不涉及到硬件消耗,所以功耗最低,通过算法和基站数据能够得到比较理想的定位精度,只要手机有信号,就能通过距离最近的(不少于)3个信号塔的强弱,大概判定手机当前的位置。
混合定位就更好理解了,就是将上面两种方法结合,先通过联网定位迅速判断手机的大概区域,再搜索该区域的卫星实现快速定位。
为什么会出现偏差
1
外界因素
如果你在立交桥下、隧道或室内,GPS基本就残废了。在接收不到GPS信号时,手机就会自动切入到基站定位状态下。此时的定位准确性完全就是比拼人品,如果你身处的环境网络差,定位偏差自然会吓死你。如果你恰好在一个和地图APP有合作的商场(进行室内导航优化),那你会发现定位的误差可能非常小。
对了,GPS信号有时也会不靠谱哦。具体的原因比如当前天气不好,大气层对电磁波产生了折射效应;再比如你在汽车里,但手机没有放在靠窗的位置,GPS信号同样会受到汽车铁皮的影响而导致搜星失败或信号变弱。
2
内部因素
在同样一个位置,有些型号的手机可以实现“瞬间定位”,而且准确性极高,但有些手机可能几分钟都无法准确定位。是因为现在主流的智能手机都将GPS芯片技术集成在CPU或基带芯片里,但是提供CPU或基带芯片的厂商不止一家,产品各种各样,所以产品的性能难免会存在差异,这也是造成GPS定位出现偏差的一个因素。
3
Specially
据悉,普通GPS定位出来的数值都是基于WSG-84坐标系标准,这是世界通用的坐标系。我国的地图标准坐标系是GCJ-02,GCJ-02和WSG-84之间的坐标系转换算法是保密的。
这个保密插件也叫做加密插件或者加偏或者SM模组,其实就是对真实坐标系统进行人为的加偏处理,按照几行代码的算法,将真实的坐标加密成虚假的坐标,而这个加偏并不是线性的加偏,所以各地的偏移情况都会有所不同。而加密后的坐标也常被人称为火星坐标系统,转换过后会出现不同程度的偏差,这也可能是手机地图定位出现偏差的原因之一。
其实,手机地图定位出现偏差,并不是单单的手机本身引起的,外界很多因素都在影响着手机地图定位的精准度,所以我们在使用手机地图定位时,尽量避免人为因素造成的影响,结合实时环境使用,使其最大程度辅助我们的生活,为生活带来便捷。
参考技术A现在一般卫星是动态卫星,在行进中比较容易发现,反馈信号,但是在你停下来以后,它会较难定位或反复定位导致偏差,是正常现象
OpenCV,为啥我的鱼眼相机校准这么差?
【中文标题】OpenCV,为啥我的鱼眼相机校准这么差?【英文标题】:OpenCV, why the calibration of my fisheye camera is so bad?OpenCV,为什么我的鱼眼相机校准这么差? 【发布时间】:2021-12-30 07:02:33 【问题描述】:我正在尝试设置鱼眼相机,用于相对于特定参考框架进行对象定位。
我尝试了 OpenCV 鱼眼模块和来自 calibrateCamera() 的有理模型进行校准。我获得了this result。
我收集了 2 个不同的datasets,一个是在大部分靠近相机的地方拍摄的校准图像 (ds1),另一个是从远处拍摄的图像 (ds2)。 ds12是两者合并得到的数据集。
nok4表示k4固定为0的鱼眼模型。rm是来自cv2.calibrateCamera()的有理模型
相机具有 178° 水平 FOV 和 101° 垂直 FOV,畸变主要在图像的中心进行了校正,而在图像的最外侧部分的结果令人失望。
我做错了吗?我可以做些什么来改善结果?
编辑
这是我用于两个校准过程的代码:
import cv2 as cv
import os
import numpy as np
cwd = os.path.dirname(os.path.realpath(__file__))
os.chdir(cwd)
number = None
folder_name = "merged_images"
if number is not None:
folder_name += "_" + str(number)
points_path = os.path.join(folder_name, "dataset", "good_detections")
npz = np.load(os.path.join(points_path, "points.npz"))
square_size = 0.02435
imgpoints = npz["imgpoints"]
objpoints = npz["objpoints"] * square_size
file_names = npz["file_names"]
shuffle = True
if shuffle:
if "indices.npz" in os.listdir(points_path):
p = np.load(os.path.join(points_path, "indices.npz"))["indices"]
else:
print("Random indices assigned")
p = np.random.permutation(len(imgpoints))
imgpoints = imgpoints[p]
objpoints = objpoints[p]
file_names = file_names[p]
img = cv.imread(os.path.join(points_path, file_names[2].replace("detected_", "")))
flag_list = [
cv.CALIB_RATIONAL_MODEL,
# cv.CALIB_ZERO_TANGENT_DIST,
]
calibration_flags = 0
for flag in flag_list:
calibration_flags += flag
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
shape = gray.shape[::-1]
ret, mtx, dist, rvecs, tvecs = cv.calibrateCamera(objpoints,
imgpoints,
shape,
None,
None,
flags = calibration_flags
)
h, w = img.shape[:2]
newcameramtx, roi = cv.getOptimalNewCameraMatrix(mtx, dist, (w,h), 1, (w,h))
dst = cv.undistort(img, mtx, dist, None, newcameramtx)
# fisheye model
flag_list = [
cv.fisheye.CALIB_RECOMPUTE_EXTRINSIC,
cv.fisheye.CALIB_CHECK_COND,
cv.fisheye.CALIB_FIX_SKEW,
# cv.fisheye.CALIB_FIX_K4,
# cv.fisheye.CALIB_FIX_K3,
# cv.fisheye.CALIB_FIX_K2,
# cv.fisheye.CALIB_FIX_K1,
]
calibration_flags = 0
for flag in flag_list:
calibration_flags += flag
N_OK = len(objpoints)
K = np.zeros((3, 3))
D = np.zeros((4, 1))
rvecs = [np.zeros((1, 1, 3), dtype=np.float64) for i in range(N_OK)]
tvecs = [np.zeros((1, 1, 3), dtype=np.float64) for i in range(N_OK)]
n_objpoints = [np.expand_dims(objp, 0) for objp in objpoints]
all_true_points = list(n_objpoints)
all_image_points = list(imgpoints)
all_frames = list(file_names)
rejected = []
counter = 0
while True:
try:
rms, mtx, dist, rvecs, tvecs = \
cv.fisheye.calibrate(
all_true_points,
all_image_points,
gray.shape[::-1],
K,
D,
rvecs,
tvecs,
calibration_flags,
(cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 1e-3)
)
print('Found a calibration based on well-conditioned images.'.format(len(all_true_points)))
break
except cv.error as err:
try:
idx = int(str(err).split('array ')[1][0]) # Parse index of invalid image from error message
all_true_points.pop(idx)
all_image_points.pop(idx)
rejected.append(all_frames.pop(idx))
print(f"counter. Removed ill-conditioned image idx from the data. Trying again...".format(idx))
counter += 1
except IndexError:
raise err
h,w = img.shape[:2]
DIM = (w, h)
dim1 = img.shape[:2][::-1] # dim1 is the dimension of input image to un-distort
dim2 = None
dim3 = None
balance = 1
assert dim1[0]/dim1[1] == DIM[0]/DIM[1], "Image to undistort needs to have same aspect ratio as the ones used in calibration"
if not dim2:
dim2 = dim1
if not dim3:
dim3 = dim1
scaled_K = K * dim1[0] / DIM[0] # The values of K is to scale with image dimension.
scaled_K[2][2] = 1.0 # Except that K[2][2] is always 1.0
# This is how scaled_K, dim2 and balance are used to determine the final K used to un-distort image. OpenCV document failed to make this clear!
new_K = cv.fisheye.estimateNewCameraMatrixForUndistortRectify(scaled_K, D, dim2, np.eye(3), balance=balance)
map1, map2 = cv.fisheye.initUndistortRectifyMap(scaled_K, D, np.eye(3), new_K, dim3, cv.CV_16SC2)
undistorted_img = cv.remap(img, map1, map2, interpolation=cv.INTER_LINEAR, borderMode=cv.BORDER_CONSTANT)
new_img = cv.hconcat([undistorted_img, img])
使用以下代码执行角点提取:
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.
file_names = [] # files analyzed
for file in os.listdir(detections_path):
if file.startswith("hd_frame"):
frame = cv.imread(os.path.join(detections_path, file))
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
found, corners = cv.findChessboardCorners(gray, (9,6), None)
if found:
file_name = "detected_" + file
objpoints.append(objp)
imgpoints.append(corners)
# save file_name
file_names.append(file_name)
corners2 = cv.cornerSubPix(gray, corners, (11,11), (-1,-1), criteria)
# Draw and display the corners
cv.drawChessboardCorners(frame, (9,6), corners2, found)
# save image and points
cv.imwrite(os.path.join(detections_path, file_name), frame)
【问题讨论】:
你能添加你正在运行的代码吗? 【参考方案1】:您可以使用单个图像进行校准,如下所述:https://discorpy.readthedocs.io/en/latest/usage/demo_06.html。这个包中使用的校正模型可能会给你比opencv使用的模型更好的结果:https://discorpy.readthedocs.io/en/latest/tutorials/methods.html
【讨论】:
以上是关于为啥不同的手机定位有误差。的主要内容,如果未能解决你的问题,请参考以下文章