为啥不同的手机定位有误差。

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

【讨论】:

以上是关于为啥不同的手机定位有误差。的主要内容,如果未能解决你的问题,请参考以下文章

GPS定位 为啥与实际位置有差异?怎么调整?

我的手机GPS误差很大怎么回事?

C++浮点数误差是啥

C语言浮点数误差如何解决?如下

C语言浮点数误差的解决

js字符串转数字长度限制|超过长度有误差