微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

OpenCV - 计算图像中两个边缘之间的距离

如何解决OpenCV - 计算图像中两个边缘之间的距离

我正在尝试计算图像中两个边缘之间的距离(以像素数为单位)。我已经使用 cv2.warpPerspective 方法校正了图像透视,并将生成的图像转换为灰度,然后使用高斯模糊进行过滤。我尝试了各种阈值方法,发现 cv2.ADAPTIVE_THRESH_GAUSSIAN 效果最好。从自适应高斯阈值的结果可以看出,其他方法噪声太大或错过了对象左侧的第二个边缘。

import cv2
import numpy as np
import matplotlib.pyplot as plt

# Load the image
imgRoadvR10 = cv2.imread('sampleimage.jpg') # image is already corrected for perspective warp using cv2.warpPerspective

# convert to grayscale
imgRoadvR10_GrayPersp = cv2.cvtColor(imgRoadvR10,cv2.COLOR_BGR2GRAY)

# gaussian blur
a10lvR10_gblur = cv2.GaussianBlur(imgRoadvR10_GrayPersp,(5,5),0)

# Try different thresholding methods
ret,a10lvR10_th1 = cv2.threshold(a10lvR10_gblur,127,255,cv2.THRESH_BINARY)
a10lvR10_th2 = cv2.adaptiveThreshold(a10lvR10_gblur,cv2.ADAPTIVE_THRESH_MEAN_C,\
            cv2.THRESH_BINARY,11,2)
a10lvR10_th3 = cv2.adaptiveThreshold(a10lvR10_gblur,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
            cv2.THRESH_BINARY_INV,2)

# Otsu's thresholding
ret2,a10lvR10_th4 = cv2.threshold(a10lvR10_gblur,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
print(ret2)

# Plot results
plt.figure()
titles = ['Original Image','Global Thresholding (v = 127)','Adaptive Mean Thresholding','Adaptive Gaussian Thresholding','OTSU Thresholding']
images = [a10lvR10_gblur,a10lvR10_th1,a10lvR10_th2,a10lvR10_th3,a10lvR10_th4]

for i in range(5):
    plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

Results of different thresholding

仔细看看自适应高斯阈值的结果:

adaptive gaussian thresholding

我想找到这个矩形对象的宽度。宽度是从左侧的第二个边缘到右侧的边缘测量的(见下图):

enter image description here

如何测量宽度?我一直在阅读形态学操作和边缘检测,但不确定下一步如何进行。任何建议将不胜感激

解决方法

这不是最好的主意,我认为可以获得更合乎逻辑和更简单的解决方案。但是,这个想法可能对您有所帮助。

import cv2
import numpy as np

#load image
im = cv2.imread("test3.jpg",1)

#Convert to gray
mask = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)

#convert to black and white
mask = cv2.threshold(mask,127,255,cv2.THRESH_BINARY)[1]

#try to remove noise
#you can just use median blur or any other method
mask = cv2.erode(mask,np.ones((8,0),"uint8"))
mask = cv2.dilate(mask,np.ones((32,"uint8"))
mask = cv2.medianBlur(mask,9)

#save cleaned image
cv2.imwrite("out1.jpg",mask)

输出图像的更清晰版本:

out1:

enter image description here


接下来我们可以得到线条的坐标。我从左边得到了第一行的坐标。我认为您必须稍微更改代码才能获得侧边栏的坐标。

h = len(mask) - 1


def count(row):
    counter = 0
    for i in range(0,len(row)):
        if row[i] == 255:
            break
        counter += 1
    return counter


def line(im,pt1,pt2,color,thickness):
    im = cv2.line(
        img=im,pt1=pt1,pt2=pt2,color=color,thickness=thickness,lineType=cv2.LINE_AA,)
    return im


def center(x1,y1,x2,y2):
    return (int((x1 + x2) / 2),int((y1 + y2) / 2))


topLeft = count(mask[0])
bottomLeft = count(mask[h])
# to shadow and hide the old left line
mask = line(mask,(topLeft,(bottomLeft,h),(0,80)

topRight = count(mask[0])
bottomRight = count(mask[h])
# to shadow and hide the old right line
mask = line(mask,(topRight,(bottomRight,80)

mask = cv2.cvtColor(mask,cv2.COLOR_GRAY2BGR)

# to draw new clean left line
mask = line(mask,(128,255),25)
# to draw new clean right line
mask = line(mask,25)

a = center(topLeft,bottomLeft,h)
b = center(topRight,bottomRight,h)
mask = line(mask,a,b,25)

cv2.imwrite("out2.jpg",mask)

out2:

enter image description here


现在您可以计算“a”和“b”之间的距离。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。