openCV 3.0 python LineIterator

moh*_*san 18 python opencv opencv3.0

我想使用python在openCV 3.0中使用LineIterator,是否仍然可以使用为python构建的openCV 3.0?似乎互联网上的答案都指向cv.InitLineIterator,它是cv模块的一部分.我已尝试导入此模块,但似乎它不包含在当前版本中.它是否已重命名或严格删除?

moh*_*san 48

我已经解决了自己的问题.行迭代器似乎在cv2库中不可用.因此,我制作了自己的行迭代器.没有使用循环,因此它应该非常快.如果有人需要,这是代码:

def createLineIterator(P1, P2, img):
    """
    Produces and array that consists of the coordinates and intensities of each pixel in a line between two points

    Parameters:
        -P1: a numpy array that consists of the coordinate of the first point (x,y)
        -P2: a numpy array that consists of the coordinate of the second point (x,y)
        -img: the image being processed

    Returns:
        -it: a numpy array that consists of the coordinates and intensities of each pixel in the radii (shape: [numPixels, 3], row = [x,y,intensity])     
    """
   #define local variables for readability
   imageH = img.shape[0]
   imageW = img.shape[1]
   P1X = P1[0]
   P1Y = P1[1]
   P2X = P2[0]
   P2Y = P2[1]

   #difference and absolute difference between points
   #used to calculate slope and relative location between points
   dX = P2X - P1X
   dY = P2Y - P1Y
   dXa = np.abs(dX)
   dYa = np.abs(dY)

   #predefine numpy array for output based on distance between points
   itbuffer = np.empty(shape=(np.maximum(dYa,dXa),3),dtype=np.float32)
   itbuffer.fill(np.nan)

   #Obtain coordinates along the line using a form of Bresenham's algorithm
   negY = P1Y > P2Y
   negX = P1X > P2X
   if P1X == P2X: #vertical line segment
       itbuffer[:,0] = P1X
       if negY:
           itbuffer[:,1] = np.arange(P1Y - 1,P1Y - dYa - 1,-1)
       else:
           itbuffer[:,1] = np.arange(P1Y+1,P1Y+dYa+1)              
   elif P1Y == P2Y: #horizontal line segment
       itbuffer[:,1] = P1Y
       if negX:
           itbuffer[:,0] = np.arange(P1X-1,P1X-dXa-1,-1)
       else:
           itbuffer[:,0] = np.arange(P1X+1,P1X+dXa+1)
   else: #diagonal line segment
       steepSlope = dYa > dXa
       if steepSlope:
           slope = dX.astype(np.float32)/dY.astype(np.float32)
           if negY:
               itbuffer[:,1] = np.arange(P1Y-1,P1Y-dYa-1,-1)
           else:
               itbuffer[:,1] = np.arange(P1Y+1,P1Y+dYa+1)
           itbuffer[:,0] = (slope*(itbuffer[:,1]-P1Y)).astype(np.int) + P1X
       else:
           slope = dY.astype(np.float32)/dX.astype(np.float32)
           if negX:
               itbuffer[:,0] = np.arange(P1X-1,P1X-dXa-1,-1)
           else:
               itbuffer[:,0] = np.arange(P1X+1,P1X+dXa+1)
           itbuffer[:,1] = (slope*(itbuffer[:,0]-P1X)).astype(np.int) + P1Y

   #Remove points outside of image
   colX = itbuffer[:,0]
   colY = itbuffer[:,1]
   itbuffer = itbuffer[(colX >= 0) & (colY >=0) & (colX<imageW) & (colY<imageH)]

   #Get intensities from img ndarray
   itbuffer[:,2] = img[itbuffer[:,1].astype(np.uint),itbuffer[:,0].astype(np.uint)]

   return itbuffer
Run Code Online (Sandbox Code Playgroud)

  • 感谢您分享@mohikhsan。只是要注意,该行与`cv2.drawLine()`给出的行略有不同:您的行不包含第一个点`P1',而`cv2.drawLine()`包含它。 (2认同)

tre*_*tix 10

编辑:来自 scikit-image 的函数行可以产生相同的效果,并且它比我们可以编写的任何代码都快。

from skimage.draw import line
# being start and end two points (x1,y1), (x2,y2)
discrete_line = list(zip(*line(*start, *end)))
Run Code Online (Sandbox Code Playgroud)

而且 timeit 结果相当快。所以,用这个。

旧的“已弃用”答案:

正如之前的答案所说,它没有实现,所以你必须自己做。我不是从头开始做的,我只是以一种更高级、更现代的方式重写了函数的某些部分,以正确处理所有情况,而不像投票最多的答案对我来说不起作用。我从这里拿了这个例子,做了一些清理和一些造型。随意评论它。我还添加了像源代码一样的clipline测试,可以在OpenCv 4.x源代码的drawing.cpp中找到,谢谢大家的参考和辛勤工作。

from skimage.draw import line
# being start and end two points (x1,y1), (x2,y2)
discrete_line = list(zip(*line(*start, *end)))
Run Code Online (Sandbox Code Playgroud)


Dav*_*vid 7

我比较了本页提供的 4 种方法:

使用 python 2.7.6 和 scikit-image 0.9.3 并进行一些小的代码更改。
图像输入是通过 OpenCV 进行的。
线段 (1, 76) 到 (867, 190)

方法 1: Sci-kit 图像线
计算时间:0.568 ms
找到的像素数:867
正确的起始像素:是
正确的结束像素:是

方法2:来自@trenixjetix代码的代码
似乎存在图像宽度和高度翻转的错误。
计算时间:0.476 ms
找到的像素数:866
正确的起始像素:是
正确的结束像素:否,关闭 1

方法 3:来自 ROS.org 的代码
https://answers.ros.org/question/10160/opencv-python-lineiterator-returning-position-information/ 计算时间:0.433 ms(应与方法 2 相同)
像素数找到:866
正确的起始像素:是
正确的结束像素:否,关闭 1

方法 4:来自 @mohikhsan 的代码
计算时间:0.156 ms
找到的像素数:866
正确的起始像素:否,关闭 1
正确的结束像素:是

摘要:
最准确的方法: Sci-kit Image Line
最快的方法: 来自 @mohikhsan 的代码

如果有一个与 OpenCV C++ 实现相匹配的 python 实现会很好吗?
https://github.com/opencv/opencv/blob/master/modules/imgproc/src/drawing.cpp
或使用 python 生成器:
https://wiki.python.org/moin/Generators


Roy*_*rot 5

这不是一种奇特的方法,而是一种有效且非常非常简单的一句话:

points_on_line = np.linspace(pt_a, pt_b, 100) # 100 samples on the line
Run Code Online (Sandbox Code Playgroud)

如果你想大致获取沿途的每个像素

points_on_line = np.linspace(pt_a, pt_b, np.linalg.norm(pt_a - pt_b))
Run Code Online (Sandbox Code Playgroud)

(例如,样本数为 A 点和 B 点之间的像素数)

例如:

pt_a = np.array([10, 11])
pt_b = np.array([45, 67])
im = np.zeros((80, 80, 3), np.uint8)
for p in np.linspace(pt_a, pt_b, np.linalg.norm(pt_a-pt_b)):
    cv2.circle(im, tuple(np.int32(p)), 1, (255,0,0), -1)
plt.imshow(im)
Run Code Online (Sandbox Code Playgroud)

线上的点