问题描述
我一直在研究和尝试几个函数来获得我想要的东西,但我觉得我可能想多了。 我的代码的一个版本如下。示例图片为 here。
我的最终目标是找到近似线相对于框架(绿线)的角度(黄线)Final 我什至还没到程序的角度部分。
我从下面的代码中得到的结果如下。 Canny Closed Small Removed
有人有更好的方法来创建差异并建立估计线吗? 任何帮助表示赞赏。
import cv2
import numpy as np
pX = int(512)
pY = int(768)
img = cv2.imread('IMAGE LOCATION',cv2.IMREAD_COLOR)
imgS = cv2.resize(img,(pX,pY))
aimg = cv2.imread('IMAGE LOCATION',cv2.IMREAD_GRAYSCALE)
# Blur image to reduce noise and resize for viewing
blur = cv2.medianBlur(aimg,5)
rblur = cv2.resize(blur,(384,512))
canny = cv2.Canny(rblur,120,255,1)
cv2.imshow('canny',canny)
kernel = np.ones((2,2),np.uint8)
#fringeMesh = cv2.dilate(canny,kernel,iterations=2)
#fringeMesh2 = cv2.dilate(fringeMesh,None,iterations=1)
#cv2.imshow('fringeMesh',fringeMesh2)
closing = cv2.morphologyEx(canny,cv2.MORPH_CLOSE,kernel)
cv2.imshow('Closed',closing)
nb_components,output,stats,centroids = cv2.connectedComponentsWithStats(closing,connectivity=8)
#connectedComponentswithStats yields every separated component with @R_817_4045@ion on each of them,such as size
sizes = stats[1:,-1]; nb_components = nb_components - 1
min_size = 200 #num_pixels
fringeMesh3 = np.zeros((output.shape))
for i in range(0,nb_components):
if sizes[i] >= min_size:
fringeMesh3[output == i + 1] = 255
#contours,_ = cv2.findContours(fringeMesh3,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
#cv2.drawContours(fringeMesh3,contours,-1,(0,0),1)
cv2.imshow('final',fringeMesh3)
#cv2.imshow("Natural",imgS)
#cv2.imshow("img",img)
cv2.imshow("aimg",aimg)
cv2.imshow("Blur",rblur)
cv2.waitKey()
cv2.destroyAllWindows()
解决方法
您可以在每列中遇到的第一个白色像素上拟合一条直线,从底部开始。
我不得不修剪你的图片,因为你分享了一个带有窗口装饰、标题和框架的屏幕截图,而不是你的实际图片:
import cv2
import math
import numpy as np
# Load image as greyscale
im = cv2.imread('trimmed.jpg',cv2.IMREAD_GRAYSCALE)
# Get index of first white pixel in each column,starting at the bottom
yvals = (im[::-1,:]>200).argmax(axis=0)
# Make the x values 0,1,2,3...
xvals = np.arange(0,im.shape[1])
# Fit a line of the form y = mx + c
z = np.polyfit(xvals,yvals,1)
# Convert the slope to an angle
angle = np.arctan(z[0]) * 180/math.pi
注1:z
(拟合结果)的值为:
array([ -0.74002694,428.01463745])
这意味着你正在寻找的线的方程是:
y = -0.74002694 * x + 428.01463745
即y 轴截距位于图像底部的第 428 行。
注意 2:尽量避免将 JPEG 格式作为图像处理中的中间格式 - 它是有损的并且会改变您的像素值 - 所以在您设置阈值并完成形态学的地方,您期望值为 255和 0,JPEG 将有损地改变这些值,您最终会再次测试范围或阈值。
,您的“封闭”图像似乎很清楚地将这两个区域分割开来,因此我建议您专注于将该边界变成一条可以执行某些操作的线。连通分量分析和轮廓检测在这里并没有真正提供任何有用的信息,因此不是必需的。
找到线角的一种非常简单的方法是找到每行中的第一个白色像素。要仅获取属于对角线的行,请不要包含该像素太靠近任一侧的行(例如,在 5% 以内)。这为您提供了两种草的边界上的一组点(像素位置)。
从那里你可以做一个线性回归来得到直线的方程,或者你可以通过对行的上半部分和下半部分的 x 值求平均值来得到两个点,然后从中计算梯度角度.
另一种方法是使用非常大的内核进行另一个形态学关闭,最终得到一个纯白色区域和一个纯黑色区域,您可以将它们变成带有 canny 或 findContours 的线。从那里你可以通过平均得到一些点,使用端点,或者从足够大的内核中给出足够平滑的结果,你可以用霍夫线检测线。