我有一张图片:
在这张图片中,OpenCV的霍夫变换无法检测到大的-45度线。
minLineLength = 150
maxLineGap = 5
line_thr = 150
linesP = cv.HoughLinesP(dst, 1, np.pi / 180, line_thr, None, minLineLength, maxLineGap)
唯一找到的线条如下所示:
![lines found](https://istack.dev59.com/gXYiT.webp)
如果我手动裁剪图片,像这样:
![cropped version where line is found](https://istack.dev59.com/o6Dez.webp)
![line found](https://istack.dev59.com/pCBWh.webp)
同时,也可能存在没有线条或者线条长度不足X轴长度的情况。例如:
![enter image description here](https://istack.dev59.com/mTLEH.webp)
![enter image description here](https://istack.dev59.com/EJtab.webp)
我有一张图片:
在这张图片中,OpenCV的霍夫变换无法检测到大的-45度线。
minLineLength = 150
maxLineGap = 5
line_thr = 150
linesP = cv.HoughLinesP(dst, 1, np.pi / 180, line_thr, None, minLineLength, maxLineGap)
我使用终端上的ImageMagick完成了这个操作,但你也可以用OpenCV完全相同的技术来实现。
步骤1
取出图像并将其旋转45度,在需要的地方引入黑色像素作为背景:
convert 45.jpg -background black -rotate 45 result.png
步骤2
现在,在之前的命令基础上,将每个像素设置为其周围1像素宽、250像素高的框中位数:
convert 45.jpg -background black -rotate 45 -statistic median 1x250 result.png
步骤三
现在,基于之前的命令,再次将其旋转回45度:
convert 45.jpg -background black -rotate 45 -statistic median 1x250 -rotate -45 result.png
因此,总体而言,整个处理过程如下:
convert input.jpg -background black -rotate 45 -statistic median 1x250 -rotate -45 result.png
显然,然后将其裁剪回原始大小,并与原始图像并排附加以进行检查:
convert 45.jpg -background black -rotate 45 -statistic median 5x250 -rotate -45 +repage -gravity center -crop 184x866+0+0 result.png
convert 45.jpg result.png +append result.png
你也可以使用平均值
统计加阈值而不是中位数
,因为它比排序查找中位数更快,但它往往会导致模糊:
convert 45.jpg -background black -rotate 45 -statistic mean 1x250 result.png
你新添加的图片将被处理成以下结果:
#!/usr/bin/env python3
import cv2
import numpy as np
# Load image as greyscale
im = cv2.imread('45.jpg',cv2.IMREAD_GRAYSCALE)
# Pad with border so it isn't cropped when rotated
bw=300
bordered = cv2.copyMakeBorder(im, top=bw, bottom=bw, left=bw, right=bw, borderType= cv2.BORDER_CONSTANT)
# Rotate -45 degrees
w, h = bordered.shape
M = cv2.getRotationMatrix2D((h/2,w/2),-45,1)
paddedrotated = cv2.warpAffine(bordered,M,(h,w))
# DEBUG cv2.imwrite('1.tif',paddedrotated)
# Sum the elements of each column and find column with most white pixels
colsum = np.sum(paddedrotated,axis=0,dtype=np.float)
col = np.argmax(colsum)
# DEBUG cv2.imwrite('2.tif',colsum)
# Fill with black except for the line we have located which we make white
paddedrotated[:,:] = 0
paddedrotated[:,col] = 255
# Rotate back to straight
w, h = paddedrotated.shape
M = cv2.getRotationMatrix2D((h/2,w/2),45,1)
straight = cv2.warpAffine(paddedrotated,M,(h,w))
# Remove padding and save to disk
straight = straight[bw:-bw,bw:-bw]
cv2.imwrite('result.png',straight)
col = np.argmax(colsum)
使用一些基本三角函数来计算在原始图像中意味着什么。
这是输出结果:
关键词: 线检测、检测线、旋转、填充、边框、投影、图像、图像处理、Python、OpenCV、仿射变换、Hough变换
col = np.argmax(colsum)
处。 - Mark Setchellimg = cv.imread('image.jpg')
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(img_gray, 127, 255, 0)
img2, contours, hierarchy = cv.findContours(thresh, CHAIN_APPROX_SIMPLE ,cv.RETR_EXTERNAL)
这将返回许多轮廓,因此请使用循环仅保存足够长的轮廓。由于图像大小为814x1041像素,我假设如果轮廓至少为图像宽度的10%,即接近100,则该轮廓足够长(您显然必须优化此值)。
long_contours = []
for contour in contours[i]:
perimeter = cv2.arcLength(contour,True)
if (perimeter > 0.1 * 1018) # 10% of the image width
long_contours.append(contour)
for long_contour in long_contours:
rect = cv2.minAreaRect(long_contour)
aspec_ratio = rect.width / rect.height
if aspec_ratio > 8 :
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(img,[box],0,(255,255,255),cv.FILLED)
您的原始代码非常好。唯一的问题是您的图像包含太多信息,这会混淆累加器分数。如果您将线阈值增加到255,一切都会解决。
minLineLength = 150
maxLineGap = 5
line_thr = 255
linesP = cv2.HoughLinesP(dst, 1, np.pi / 180.0, line_thr, None, minLineLength, maxLineGap)
[ 1 41 286 326]
[ 0 42 208 250]
[ 1 42 286 327]
由于与上述相同的原因,在同一区域检测到了5条线。使用形态学运算或距离变换来减小像素大小应该可以解决这个问题。
[110 392 121 598]
[112 393 119 544]
[141 567 147 416]
[ 29 263 29 112]
[ 0 93 179 272]