Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python cv.Minarealect2和ArcGIS(GIS软件)之间的结果不一致。可能的错误?_Python_Debugging_Opencv_Geometry - Fatal编程技术网

Python cv.Minarealect2和ArcGIS(GIS软件)之间的结果不一致。可能的错误?

Python cv.Minarealect2和ArcGIS(GIS软件)之间的结果不一致。可能的错误?,python,debugging,opencv,geometry,Python,Debugging,Opencv,Geometry,我有一组从多边形导出的点。我正在测试几种解决方案,以获得最小面积或矩形。作为基准,我使用的是ArcGIS(10.1) 一种解决方案是使用OpenCV的cv.minarealect2() 函数cv.minarearct2查找 通过为二维点集和点集构建凸包,获得二维点集的最小面积 将旋转卡钳技术应用于船体 当我在shapefile中转换box\u vtx以便在ArcGIS中查看并与进行比较时,我可以看到此差异,如下图所示, 其中: 红色=多边形的边界 蓝色=ArGIS(10.1)中最小面积的矩形

我有一组从多边形导出的点。我正在测试几种解决方案,以获得最小面积或矩形。作为基准,我使用的是ArcGIS(10.1)

一种解决方案是使用OpenCV的
cv.minarealect2()

函数cv.minarearct2查找 通过为二维点集和点集构建凸包,获得二维点集的最小面积 将旋转卡钳技术应用于船体

当我在shapefile中转换
box\u vtx
以便在ArcGIS中查看并与进行比较时,我可以看到此差异,如下图所示, 其中:

  • 红色=多边形的边界
  • 蓝色=ArGIS(10.1)中最小面积的矩形
  • 黄色和黑色=具有OpenCV最小面积的矩形

使用OpenCV与本文中提出的解决方案进行比较:

导入osgeo.gdal,ogr
导入cv
poly=“…\\polygon.shp”
shp=osgeo.ogr.Open(多边形)
layer=shp.GetLayer()
feature=layer.GetFeature(0)
几何图形=特征。GetGeometryRef()
pts=geometry.GetGeometryRef(0)
#获取多边形边界的点(上面的点)
点数=[]
对于xrange中的p(pts.GetPointCount()):
points.append((pts.GetX(p),pts.GetY(p)))
#凸包
CH1=几何体.convxhull
#我没有找到一种方法来提取这些点
打印CH1()
#使用openCV
cvxHull=cv.ConvexHull2(points,cv.CreateMemStorage(),return_points=True)
打印cvxHull

我还没有看过OpenCV代码,但在计算中,大x,y乘积很可能是从其他大x,y乘积中减去的。x值中的偏移量约为19位,y值中的偏移量约为23位,因此这种减法可能会导致从典型的双精度数字携带的53位中损失约42位。(见维基百科)黄色和黑色矩形的大小和形状看起来合理,但显示的宽度和长度(10.285…,18.335…)与(10.393,18.037…)有1%的不同,后者显示在

简而言之,OpenCV在
minarealect2()
BoxPoints()
中可能存在舍入、下溢或溢出问题

要检查或测试的内容包括:
•显示和打印OpenCV凸包计算的点
•在图形上,显示OpenCV和ArcGIS矩形的中心,并打印从这些中心到所显示矩形角的距离
•使用转换后的数据集(见下文)重新运行计算和图表,以减少相互减去大量数据的下溢效应

在OpenCV计算之前转换数据集可以将丢失的位数减半。通过如下代码生成一组新点,并尝试使用新数据集进行计算:

s = points     # points = original data set
n = len(s)
cx = sum(zip(*s)[0])/n
cy = sum(zip(*s)[1])/n
points = map(lambda p: (p[0]-cx, p[1]-cy), s)
# Now points = translated data set
在上面的代码中,
zip(*s)
将(x,y)点列表解压为两个列表,其中x值列在zip(*s)[0]中,y值列在zip(*s)[1]中。因此(cx,cy)表示s中列出的点的质心。映射表达式将函数应用于iterable的元素。该函数返回一个点,该点转换为(-cx,-cy)。贴图表达式的值是已转换点的列表。注意,最好设置
cx=int(sum(zip(*s)[0])/n)
cy=int(sum(zip(*s)[1])/n)
,以便晶格点仍然是晶格点,如果这是您正在计算的。删除较大偏移的有利效果仍然存在,并且在转换过程中会出现较少的舍入

注:我使用从数据集和外壳中减去的偏移量进行测试(假设外壳如中所示,可能如中所示),得到的结果不一致,与我在#13542855中给出的方法的结果不一致。因此,根据您的数字很难确定问题发生在哪里。下面显示了一个更简单的测试用例。该测试清楚地表明,大偏移会导致精度差。也许您可以通过ArcGIS运行类似的测试数据。以下是测试结果的一半。minarealect2()和BoxPoints()被赋予基数,并添加了偏移量;对于显示的结果,计算后会减去偏移量,以便比较结果。理想情况下,每列中的所有数字(ox、oy列除外)都是相同的;但随着ox,oy的增加,它们开始不同,很快变得几乎随机

      ox         oy      T cx      T cy    height     width     theta
       0          0    6.2500    7.7500   11.5709   13.7281  -78.6901
      64        125    6.2500    7.7500   11.5709   13.7281  -78.6901
     256        625    6.2500    7.7501   11.5709   13.7281  -78.6901
    1024       3125    6.2500    7.7500   11.5709   13.7281  -78.6901
    4096      15625    6.2500    7.7510   11.5709   13.7281  -78.6901
   16384      78125    6.2500    7.7578   11.5709   13.7281  -78.6901
   65536     390625    6.2500    7.7812   11.5709   13.7281  -78.6901
  262144    1953125    6.3125    7.7500   11.5709   13.7281  -78.6901
 1048576    9765625    6.2500    8.0000   11.5709   13.7281  -78.6901
 4194304   48828125    7.0000   11.0000   12.0000   14.0000  -90.0000
16777216  244140625    8.0000   15.0000   16.0000   14.0000  -90.0000
67108864 1220703125    8.0000  -21.0000   16.0000    0.0000   -0.0000
以下是生成上述数据的代码:

#!/usr/bin/python
import cv
base = [(1,1), (0,4), (2,9), (5,11), (8,14), (13,9), (14,4), (12,3), (2,1), (1,1)]
ox, oy, boxes = 0, 0, []
print '        ox         oy      T cx      T cy    height     width     theta'
for i in range(3,15):
    poly = map(lambda p: (p[0]+ox, p[1]+oy), base)
    (x,y), (w,h), th = cv.MinAreaRect2(poly)
    boxes.append((ox, oy, cv.BoxPoints(((x,y),(w,h),th))))
    print ('{:10d} {:10d} {:9.4f} {:9.4f} {:9.4f} {:9.4f} {:9.4f}'.format(
            ox, oy, x-ox, y-oy, w, h, th))
    ox, oy = 4**i, 5**i

print '\n        ox         oy       T x       T y       T x       T y       T x       T y       T x       T y'
for (ox, oy, box) in boxes:
    print '{:10d} {:10d}'.format(ox, oy),
    for p in box:
        print '{:9.4f} {:9.4f}'.format(p[0]-ox, p[1]-oy),
    print

我在寻找最小面积边界矩形的Python解决方案时遇到了这个问题

这是我的实现,已经用Matlab进行了验证:

亲爱的jwpat7。你认为我需要向OpenCV的人发送反馈吗?PS:生活并不容易。今天早上,我非常高兴地找到了计算短轴和长轴的方法。我是诚实的。昨天晚上,我试图将您的方法压缩到一个函数中,但我实际上是Python编程的初学者,无法使用实际的capacity@Gianni当前位置从您的评论中我不清楚您是否能够尝试这些建议(以及它们是否有帮助)。另外,您使用的是什么版本的Python?我在Windows机器上使用的是Python 2.7。我从这个页面下载了用于Python扩展包的非官方Windows二进制文件OpenCV。问题是OpenCV是否有bug。我使用ArcGIS(处理空间数据的非常昂贵的软件)作为Benchmark@Gianni:jwpat7的任何建议是否改善了您的结果?您这样做的主要原因是什么..创建ArcGIS的替代方案,只是测试OpenCV?@martineau:我在做一个脚本(简单)在Python中,从多边形形状文件中提取多个索引。我这样做是为了几个递归:1-ArcGIS非常昂贵(超过8000美元),我只需要计算长度和宽度。2-创建一个特定的脚本t
s = points     # points = original data set
n = len(s)
cx = sum(zip(*s)[0])/n
cy = sum(zip(*s)[1])/n
points = map(lambda p: (p[0]-cx, p[1]-cy), s)
# Now points = translated data set
      ox         oy      T cx      T cy    height     width     theta
       0          0    6.2500    7.7500   11.5709   13.7281  -78.6901
      64        125    6.2500    7.7500   11.5709   13.7281  -78.6901
     256        625    6.2500    7.7501   11.5709   13.7281  -78.6901
    1024       3125    6.2500    7.7500   11.5709   13.7281  -78.6901
    4096      15625    6.2500    7.7510   11.5709   13.7281  -78.6901
   16384      78125    6.2500    7.7578   11.5709   13.7281  -78.6901
   65536     390625    6.2500    7.7812   11.5709   13.7281  -78.6901
  262144    1953125    6.3125    7.7500   11.5709   13.7281  -78.6901
 1048576    9765625    6.2500    8.0000   11.5709   13.7281  -78.6901
 4194304   48828125    7.0000   11.0000   12.0000   14.0000  -90.0000
16777216  244140625    8.0000   15.0000   16.0000   14.0000  -90.0000
67108864 1220703125    8.0000  -21.0000   16.0000    0.0000   -0.0000
#!/usr/bin/python
import cv
base = [(1,1), (0,4), (2,9), (5,11), (8,14), (13,9), (14,4), (12,3), (2,1), (1,1)]
ox, oy, boxes = 0, 0, []
print '        ox         oy      T cx      T cy    height     width     theta'
for i in range(3,15):
    poly = map(lambda p: (p[0]+ox, p[1]+oy), base)
    (x,y), (w,h), th = cv.MinAreaRect2(poly)
    boxes.append((ox, oy, cv.BoxPoints(((x,y),(w,h),th))))
    print ('{:10d} {:10d} {:9.4f} {:9.4f} {:9.4f} {:9.4f} {:9.4f}'.format(
            ox, oy, x-ox, y-oy, w, h, th))
    ox, oy = 4**i, 5**i

print '\n        ox         oy       T x       T y       T x       T y       T x       T y       T x       T y'
for (ox, oy, box) in boxes:
    print '{:10d} {:10d}'.format(ox, oy),
    for p in box:
        print '{:9.4f} {:9.4f}'.format(p[0]-ox, p[1]-oy),
    print