python - 从一点开始就保持多条线

标签 python numpy opencv image-processing cv2

我正在使用OpenCV和python进行项目,但是卡在了这个小问题上。
我在列表中存储的许多行上都有端点的坐标。有时会出现从单个点检测到多条线的情况。从这些行中,我想保持最短的行并消除所有其他行,因此我的图像将不会包含绘制多条线的任何点。
我的变量存储了最初检测到的所有行的信息(两个端点的坐标),如下所示:

var = [[Line1_EndPoint1, Line1_EndPoint2],
       [Line2_EndPoint1, Line2_EndPoint2],
       [Line3_EndPoint1, Line3_EndPoint2],
       [Line4_EndPoint1, Line4_EndPoint2],
       [Line5_EndPoint1, Line5_EndPoint2]]
其中,LineX_EndPointY(行号“X”,该行的端点“Y”)的类型为[x,y],其中x和y是图像中该点的坐标。
有人可以建议我如何解决这个问题。
您可以修改行数据的存储方式。如果您进行修改,请说明您的数据结构及其创建方式
此类数据的示例:
[[[551, 752], [541, 730]], 
 [[548, 738], [723, 548]],
 [[285, 682], [226, 676]],
 [[416, 679], [345, 678]],
 [[345, 678], [388, 674]],
 [[249, 679], [226, 676]],
 [[270, 678], [388, 674]],
 [[472, 650], [751, 473]],
 [[751, 473], [716, 561]],
 [[731, 529], [751, 473]]]
Python代码会很有意义。

最佳答案

一个Numpy解决方案
完全基于我的第一个答案可以得到相同的结果
在Numpy上。
首先定义2个功能:

  • 计算一行长度的平方:
     def sqLgth(line):
         p1, p2 = line
         return (p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2
    
  • 将 vector (一维数组)转换为列数组(二维数组)
    单列:
     def toColumn(tbl):
         return tbl.reshape(-1, 1)
    

  • 两者都将在以后使用。
    然后执行以下操作:
  • 获取行数:
     lineNo = var.shape[0]
    
  • 生成线索引(points数组中lineInd列的内容
    (将在以后创建)):
     id = np.repeat(np.arange(lineNo), 2)
    
  • 生成“来源指标”(1-开始,2-结束)以简化分析
    任何中间打印输出:
     origin = np.tile(np.array([1, 2]), lineNo)
    
  • 计算行长(以磅为单位的lgth列的内容):
     lgth = np.repeat([ sqLgth(line) for line in var ], 2)
    
  • 创建包含一些其他数据的点的列表(连续的)
    列包含原点,lineInd,x,y和lgth):
     points = np.hstack([toColumn(origin), toColumn(id),
         var.reshape(-1, 2), toColumn(lgth)])
    
  • 计算“条件数组”进行排序:
     r = np.core.records.fromarrays(points[:, 2:].transpose(),
         names='x, y, lgth')
    
  • 排序点(按x,y和lgth):
     points = points[r.argsort()]
    
  • 计算“逆唯一索引”到点:
     _, inv = np.unique(points[:,2:4], axis=0, return_inverse=True)
    
  • 将inv移位1位:
     rInv = np.roll(inv,1)
    
    将用于下一步,以获取上一个元素。
  • 生成要删除的行索引列表:
    toDrop = points[[ i for i in range(2 * lineNo)
        if inv[i] == rInv[i] ], 1]
    
    行索引(在点数组中)是重复点(元素)的索引
    inv等于前一个元素)。
    列索引(1)-指定lineInd列。
    整个结果(toDrop)是“拥有”行的索引列表
    (包含重复的点)。
  • 生成结果:var从在
    前一步:
    var2 = np.delete(var, toDrop, axis=0)
    

  • 要打印缩小的行列表,可以运行:
    for line in var2:
        print(f'{line[0]}, {line[1]}')
    
    结果是:
    [551 752], [541 730]
    [548 738], [723 548]
    [345 678], [388 674]
    [249 679], [226 676]
    [731 529], [751 473]
    
    要完全理解此代码的工作方式:
  • 分别执行每个步骤
  • 打印结果
  • 将它与先前步骤中的打印输出进行比较。

  • 有时甚至单独打印某些表达式也很有帮助
    (说明的一部分),例如var.reshape(-1, 2)-转换您的
    var(形状(10,2,2))变成点的2D数组(每行是
    一个点)。
    整个结果当然与我的第一个答案相同,
    但是正如您所写,您对 Pandas 的经验很少,现在您可以
    比较这两种方法,看看 Pandas 允许这样做的情况
    更简单,更直观的东西。
    很好的例子是按某些列排序或查找重复的行。
    在 Pandas 中,这是一个单一指示的问题,
    参数,而在Numpy中,您必须使用更多说明
    并了解各种细节和技巧,如何做到相同。

    关于python - 从一点开始就保持多条线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62833614/

    相关文章:

    python - 如何从 numpy 数组创建列表?

    python - 使用 OpenCV 将 RGB 图像转换为 LMS,反之亦然

    python - OpenCV-(-215 :Assertion failed) _src. 函数 'cv::warpPerspective' 中总计() > 0

    python - 数据帧中的.map(str) 和.astype(str) 有什么区别

    python - 如果 pandas series 的值是一个列表,如何获取每个元素的子列表?

    numpy - 条宽相等的对数多序列图

    python - 以最快的方式处理大数据集的豪斯多夫距离

    .net - 从 CvHoughCircles 获取更多信息

    python - 如何在分组条形图中为条形着色

    python - 在对应于其他两列的一列中划分两行及其关系(Python)