Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.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 OpenCV:以给定角度通过轮廓形心的线_Python_Opencv_Image Processing_Line_Contour - Fatal编程技术网

Python OpenCV:以给定角度通过轮廓形心的线

Python OpenCV:以给定角度通过轮廓形心的线,python,opencv,image-processing,line,contour,Python,Opencv,Image Processing,Line,Contour,我从下面的图像中获得了一个名为cnt的轮廓: 我可以找到像这样的质心: M = cv2.moments(cnt) centroid_x = int(M['m10']/M['m00']) centroid_y = int(M['m01']/M['m00']) 现在我想画N条线,每一条线之间360/N度,从质心开始,在所有可能的交点处切割轮廓。函数需要起点和终点,但我没有终点 如果我画了一条穿过质心的直线,斜率为Tan(360/N),我会使用按位_和找到该直线与轮廓的交点,但我无法找到绘制该直线

我从下面的图像中获得了一个名为
cnt
的轮廓:

我可以找到像这样的质心:

M = cv2.moments(cnt)
centroid_x = int(M['m10']/M['m00'])
centroid_y = int(M['m01']/M['m00'])
现在我想画N条线,每一条线之间360/N度,从质心开始,在所有可能的交点处切割轮廓。函数需要起点和终点,但我没有终点

如果我画了一条穿过质心的直线,斜率为Tan(360/N),我会使用
按位_和
找到该直线与轮廓的交点,但我无法找到绘制该直线的方法


任何关于如何划定这些界限的帮助都将不胜感激

我有些东西在工作。这有点特别,但这基本上是我写的算法。我必须重建你图像的轮廓,所以我所做的是手动读取图像,提取物体最外层的轮廓,然后从那里开始。
cv2.line
方法的优点在于,如果您画了一条超出边界的线,该线将被图像边界剪裁。这将在我编写的算法中很有用

不用多说,以下是步骤:

  • 读取图像,然后反转图像,使黑色轮廓线变为白色点
  • 检测最外面的轮廓
  • 创建原始输入图像的副本,以便我们可以绘制线条。将此
    调出
  • 创建一个“参考”图像,存储步骤2中找到的最外层轮廓
  • 检测轮廓点的质心。还可以访问图像的宽度和高度。如果没有任何宽度或高度值,请选择一个非常大的值。。。大概1000左右吧。您需要确保该值超出轮廓上任何点的最大值。另外,设置所需的角度总数,
    N
  • 对于每个角度,对于
    i=0,1
    N-1

    a。创建一个临时空白图像

    b。计算适当的角度:
    i*(360/N)
    并转换为弧度

    c。在临时图像上,从轮廓的质心到图像外部的坐标绘制一条线,以确保我们沿所需角度向图像边界绘制一条线。此行的水平分量是
    cos(360/N)
    (此处参数以度为单位),而垂直分量是
    -sin(360/N)
    (参数也以度为单位)。负数是因为在图像坐标空间中,
    y
    轴向下是正的,所以负数是要将其还原,这样正数相对于笛卡尔坐标向上。这样做的原因是,当我们计算每条线与中心的夹角时,这些夹角将是正确的,因为正角度逆时针扫掠。从质心开始,我们将移动水平方向的图像宽度和垂直方向的图像高度,以保持先前发现的水平和垂直分量。这将使我们画出边界外的线,但该线将被图像边界剪裁

    另一个复杂之处是在这个临时图像中画一条足够厚的线。如果我们画了一条只有1像素厚的线,你可能会遇到这样的情况:由于像素的采样和线的绘制方式,线与轮廓不相交。我在这里选择了5像素的厚度来确定

    d。使用此临时图像,查看哪些位置等于参考图像。对于任何相等的位置,我们已经找到了这条线与原始图像轮廓相交的位置。因此,请选择任何相交的位置,因为粗线很可能会与最外层轮廓产生多个交点

    e。使用步骤(d),从
    out
    的质心到我们在步骤(d)中找到的位置画一条线

  • 对所有角度重复步骤6<代码>输出
  • 将包含步骤6完成后的结果

    不用多说,下面是我编写的代码:

    # Step #1
    img = cv2.imread('contour.png', 0)
    img_bw = img <= 128
    img_bw = 255*img_bw.astype('uint8')
    
    # Step #2
    contours, _ = cv2.findContours(img_bw,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
    
    # Step #3
    out = img.copy()
    
    # Step #4
    ref = np.zeros_like(img_bw)
    cv2.drawContours(ref, contours, 0, 255, 1)
    
    # Step #5
    M = cv2.moments(contours[0])
    centroid_x = int(M['m10']/M['m00'])
    centroid_y = int(M['m01']/M['m00'])
    
    # Get dimensions of the image
    width = img.shape[1]
    height = img.shape[0]
    
    # Define total number of angles we want
    N = 20
    
    # Step #6
    for i in range(N):
      # Step #6a
      tmp = np.zeros_like(img_bw)
    
      # Step #6b
      theta = i*(360/N)
      theta *= np.pi/180.0
    
      # Step #6c
      cv2.line(tmp, (centroid_x, centroid_y),
               (int(centroid_x+np.cos(theta)*width),
                int(centroid_y-np.sin(theta)*height)), 255, 5)
    
      # Step #6d
      (row,col) = np.nonzero(np.logical_and(tmp, ref))
    
      # Step #6e
      cv2.line(out, (centroid_x, centroid_y), (col[0],row[0]), 0, 1)
    
    # Show the image
    # Step #7
    cv2.imshow('Output', out)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    #步骤#1
    img=cv2.imread('contour.png',0)
    
    img_bw=img我有些东西在工作。这有点特别,但这基本上是我写的算法。我必须重建你图像的轮廓,所以我所做的是手动读取图像,提取物体最外层的轮廓,然后从那里开始。
    cv2.line
    方法的优点在于,如果您画了一条超出边界的线,该线将被图像边界剪裁。这将在我编写的算法中很有用

    不用多说,以下是步骤:

  • 读取图像,然后反转图像,使黑色轮廓线变为白色点
  • 检测最外面的轮廓
  • 创建原始输入图像的副本,以便我们可以绘制线条。将此
    调出
  • 创建一个“参考”图像,存储步骤2中找到的最外层轮廓
  • 检测轮廓点的质心。还可以访问图像的宽度和高度。如果没有任何宽度或高度值,请选择一个非常大的值。。。大概1000左右吧。您需要确保该值超出轮廓上任何点的最大值。另外,设置所需的角度总数,
    N
  • 对于每个角度,对于
    i=0,1
    N-1

    a。创建一个临时空白图像

    b。计算适当的角度:
    i*(360/N)
    并转换为弧度

    c。在临时图像上,从轮廓的质心到图像外部的坐标绘制一条线,以确保
    findContours( f, contours, heirarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE );
    
    Moments M = moments( contours[0], true );
    Point2f cntr = Point2f( (int)M.m10/M.m00, (int)M.m01/M.m00 );
    circle( frame, cntr, 5, Scalar(0,0,0) );
    
    int N = 20;
    vector<float> slopes;
    for( int i=0; i<N; i++ )
        slopes.push_back( i*360.0/N ); 
    
    
    for( auto s : slopes )
        for( auto p : contours[0] )
            if( std::abs( cv::fastAtan2( p.y-cntr.y, p.x-cntr.x ) - s ) <= 0.5 )    //error margin, of sorts..
                {   finalpoints.push_back( p ); break; }
    
    cout<<"\nfound points: "<<finalpoints.size()<<endl; 
    for( auto p : finalpoints )
        line( frame, cntr, p, Scalar(0,0,0), 1 );