用粗轮廓OpenCV逼近边缘

2024-09-29 01:22:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在研究和尝试一些函数来得到我想要的,我觉得我可能想得太多了。 下面是我的代码的一个版本。示例图像是here

我的最终目标是找到近似线相对于帧(绿线)的角度(黄色)Final 我甚至还没有谈到节目的角度部分

我从下面的代码中得到的结果如下CannyClosedSmall 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 information 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, 255, 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()

Tags: imgoutputnpcomponentscv2kernelclosingimshow
2条回答

你的“封闭”图像似乎非常清楚地分割了这两个区域,所以我建议你把重点放在把边界变成一条线,你可以用它做点什么。连接组件分析和轮廓检测在这里并没有提供任何有用的信息,因此没有必要

找到线条角度的一个非常简单的方法是找到每行中的第一个白色像素。若要仅获取属于对角线一部分的行,请不要包含该像素太靠近任何一侧的行(例如,在5%以内)。这将在两种草地的边界上提供一组点(像素位置)

从那里你可以做一个线性回归,得到一个直线方程,或者你可以通过平均上半行和下半行的x值得到两个点,然后从中计算梯度角

另一种方法是用一个非常大的内核做另一个形态学上的接近,最终得到一个纯白色区域和一个纯黑色区域,你可以把它们变成一条与canny或findContours的线。从那里你可以通过平均得到一些点,使用端点,或者从一个足够大的内核中得到一个足够平滑的结果,你可以用hough线来检测线

可以从底部开始,将直线拟合到每列中遇到的第一个白色像素

我不得不修剪你的图像,因为你分享了一个屏幕抓图,其中有一个窗口装饰、标题和框架,而不是你的真实图像:

enter image description here

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

注1z(拟合结果)的值为:

array([ -0.74002694, 428.01463745])

这意味着你要寻找的直线方程是:

y = -0.74002694 * x + 428.01463745

即,y截距位于图像底部的第428行

注意2:尽量避免将JPEG格式作为图像处理中的中间格式-它会有损,并会更改像素值-因此,当您设置阈值并进行形态学处理时,您期望的值为255和0,JPEG将有损地更改这些值,并再次测试范围或阈值

相关问题 更多 >