Python 如何检测颗粒线?
我试图用cv2检测纸张上的粒状打印线。我需要线的角度。我没有太多的图像处理知识,我只需要检测线。我试图玩参数,但角度总是检测错误。谁能帮帮我吗。这是我的代码: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
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度。看见