Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/301.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 如何检测颗粒线?_Python_Opencv_Image Processing_Straight Line Detection - Fatal编程技术网

Python 如何检测颗粒线?

Python 如何检测颗粒线?,python,opencv,image-processing,straight-line-detection,Python,Opencv,Image Processing,Straight Line Detection,我试图用cv2检测纸张上的粒状打印线。我需要线的角度。我没有太多的图像处理知识,我只需要检测线。我试图玩参数,但角度总是检测错误。谁能帮帮我吗。这是我的代码: import cv2 import numpy as np import matplotlib.pylab as plt from matplotlib.pyplot import figure img = cv2.imread('CamXY1_1.bmp') crop_img = img[100:800, 300:900] blur

我试图用cv2检测纸张上的粒状打印线。我需要线的角度。我没有太多的图像处理知识,我只需要检测线。我试图玩参数,但角度总是检测错误。谁能帮帮我吗。这是我的代码:

import cv2
import numpy as np
import matplotlib.pylab as plt
from matplotlib.pyplot import figure

img = cv2.imread('CamXY1_1.bmp')
crop_img = img[100:800, 300:900]
blur = cv2.GaussianBlur(crop_img, (1,1), 0)
ret,thresh = cv2.threshold(blur,150,255,cv2.THRESH_BINARY)
gray = cv2.cvtColor(thresh,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 60, 150)

figure(figsize=(15, 15), dpi=150)
plt.imshow(edges, 'gray')

lines = cv2.HoughLines(edges,1,np.pi/180,200)
for rho,theta in lines[0]:
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = a*rho
    y0 = b*rho
    x1 = int(x0 + 3000*(-b))
    y1 = int(y0 + 3000*(a))
    x2 = int(x0 - 3000*(-b))
    y2 = int(y0 - 3000*(a))

    cv2.line(img,(x1,y1),(x2,y2),(0, 255, 0),2)

这里有一个可能的解决方案,可以在不使用Hough线变换的情况下估计线(及其角度)。其思想是使用函数来定位直线的起点和终点。此函数可以将图像缩减为单个列或行。如果我们缩小图像,我们还可以得到整个缩小图像中所有像素的总和。利用这些信息,我们可以估计直线的端点并计算其角度。以下是步骤:

  • 调整图像大小因为图像太大了
  • 通过自适应阈值获取二值图像
  • 定义图像的两个极端区域并裁剪它们
  • 使用
    SUM
    模式将
    ROI减少为一列,该模式是所有行的总和
  • 累计高于阈值的总值
  • 估计生产线的起点和终点
  • 获取线的角度
  • 代码如下:

    # imports:
    import cv2
    import numpy as np
    import math
    
    # image path
    path = "D://opencvImages//"
    fileName = "mmCAb.jpg"
    
    # Reading an image in default mode:
    inputImage = cv2.imread(path + fileName)
    
    # Scale your BIG image into a small one:
    scalePercent = 0.3
    
    # Calculate the new dimensions
    width = int(inputImage.shape[1] * scalePercent)
    height = int(inputImage.shape[0] * scalePercent)
    newSize = (width, height)
    
    # Resize the image:
    inputImage = cv2.resize(inputImage, newSize, None, None, None, cv2.INTER_AREA)
    
    # Deep copy for results:
    inputImageCopy = inputImage.copy()
    
    # Convert BGR to grayscale:
    grayInput = cv2.cvtColor(inputImage, cv2.COLOR_BGR2GRAY)
    
    # Adaptive Thresholding:
    windowSize = 51
    windowConstant = 11
    binaryImage = cv2.adaptiveThreshold(grayInput, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, windowSize, windowConstant)
    
    第一步是得到二值图像。请注意,我以前缩小了您的输入规模,因为它太大,我们不需要所有这些信息。这是二进制掩码:

    现在,我们不需要大部分图像。事实上,由于这条线横跨整个图像,我们只能“修剪”第一列和最后一列,并检查白色像素的起始位置。不过,我会将列裁剪得更宽一点,这样我们可以确保有足够的数据,并尽可能减少噪音。我将定义两个感兴趣的区域(ROI)并裁剪它们。然后,我将使用
    SUM
    模式将每个ROI减少到一列,这将给出每行所有强度的总和。在此之后,我可以累积总和超过某个阈值的位置,并近似该行的位置,如下所示:

    # Define the regions that will be cropped
    # from the original image:
    lineWidth = 5
    cropPoints = [(0, 0, lineWidth, height), (width-lineWidth, 0, lineWidth, height)]
    
    # Store the line points here:
    linePoints = []
    
    # Loop through the crop points and 
    # crop de ROI:
    
    for p in range(len(cropPoints)):
    
        # Get the ROI:
        (x,y,w,h) = cropPoints[p]
    
        # Crop the ROI:
        imageROI = binaryImage[y:y+h, x:x+w]
    
        # Reduce the ROI to a n row x 1 columns matrix:
        reducedImg = cv2.reduce(imageROI, 1, cv2.REDUCE_SUM, dtype=cv2.CV_32S)
    
        # Get the height (or lenght) of the arry:
        reducedHeight = reducedImg.shape[0]
    
        # Define a threshold and accumulate
        # the coordinate of the points:
        threshValue = 100
        pointSum = 0
        pointCount = 0
    
        for i in range(reducedHeight):
            currentValue = reducedImg[i]
    
            if currentValue > threshValue:
                pointSum = pointSum + i
                pointCount = pointCount + 1
    
        # Get average coordinate of the line:
        y = int(accX / pixelCount)
        # Store in list:
        linePoints.append((x, y))
    
    红色矩形显示我从输入图像裁剪的区域:

    请注意,我已将这两个点存储在
    linePoints
    列表中。让我们通过绘制一条连接两个点的线来检查近似值:

    # Get the two points:
    p0 = linePoints[0]
    p1 = linePoints[1]
    
    # Draw the line:
    cv2.line(inputImageCopy, (p0[0], p0[1]), (p1[0], p1[1]), (255, 0, 0), 1)
    cv2.imshow("Line", inputImageCopy)
    cv2.waitKey(0)
    
    这将产生:

    不错吧?现在我们有了这两个点,我们可以估计这条线的角度:

    # Get angle:
    adjacentSide = p1[0] - p0[0]
    oppositeSide = p0[1] - p1[1]
    
    # Compute the angle alpha:
    alpha = math.degrees(math.atan(oppositeSide / adjacentSide))
    
    print("Angle: "+str(alpha))
    
    这张照片是:

    Angle: 0.534210901840831
    

    为什么你认为角度是错误的?您是否了解,通过hough变换测量的θ角相对于直线的角度为90度。看见