c# - 轮廓的 arcLength 的结果是什么?
问题描述
我在 Google 中搜索过arcLength
,好吧,也许我能理解它,但它如何处理 EmguCV 或 OpenCV 中的图像中的轮廓?我尝试使用 MATLAB 制作一个小图像。图像是9 x 9
,我在我的图像中画了一条线,那条线是 1 像素。我在 EmguCV 中使用此代码来检测轮廓:
VectorOfVectorOfPoint cons = new VectorOfVectorOfPoint();
CvInvoke.FindContours(img_gray, cons, null, RetrType.List, ChainApproxMethod.ChainApproxNone);
for(int i=0; i<cons.Size;i++)
{
VectorOfPoint points = cons[i];
for(int x =0; x<points.Size;x++)
{
temp[points[x]] = new Gray(255);
}
double c= CvInvoke.ArcLength(cons[i], true);
textBox1.Text = c.ToString();
}
imageBox2.Image = temp;
arcLength
曾是:
- 当行为 1 像素时 ->
arcLength
为 0。 - 当线为 2 像素时 ->
arcLength
为 2。 - 当线为 3 像素时 ->
arcLength
为 4。
这是线条为 3 像素时的图像。
任何人都可以向我解释结果吗?
解决方案
arcLength
完全符合它的要求:
计算轮廓周长或曲线长度。
在您的示例中,您被findContours
(!)的一个特定问题所愚弄,即当应用于 1 像素宽的线条时!(实现问题,算法问题,“边界跟踪”的一般问题,......!?)
让我们看一下下面的例子(很抱歉在这里使用了 Python API,但概念应该变得清晰)。
示例 1: 3 x 1
黑色图像上的白线
import cv2
import numpy as np
# Generate 5 x 5 black image
img = np.zeros((5, 5), np.uint8)
# Draw 3 x 1 white line
img = cv2.rectangle(img, (1, 1), (3, 1), 255, cv2.FILLED)
# Find contours
cnts = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]
# Outputs
print(img, '\n') # Image
print(np.squeeze(cnts[0]), '\n') # Contour
print('Contour points:', cnts[0].shape[0], '\n')
print('arcLength:', cv2.arcLength(cnts[0], True))
输出:
[[ 0 0 0 0 0]
[ 0 255 255 255 0]
[ 0 0 0 0 0]
[ 0 0 0 0 0]
[ 0 0 0 0 0]]
[[1 1]
[2 1]
[3 1]
[2 1]]
Contour points: 4
arcLength: 4.0
请注意,这[2 1]
在轮廓中出现了两次,所以我们总共有四个轮廓点,两个相邻轮廓点之间的每个“距离”都是 1,因此轮廓周长(=弧长)也是 4。
示例 2: 3 x 2
黑色图像上的白色矩形
import cv2
import numpy as np
# Generate 5 x 5 black image
img = np.zeros((5, 5), np.uint8)
# Draw 3 x 2 white rectangle
img = cv2.rectangle(img, (1, 1), (3, 2), 255, cv2.FILLED)
# Find contours
cnts = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]
# Outputs
print(img, '\n') # Image
print(np.squeeze(cnts[0]), '\n') # Contour
print('Contour points:', cnts[0].shape[0], '\n')
print('arcLength:', cv2.arcLength(cnts[0], True))
输出:
[[ 0 0 0 0 0]
[ 0 255 255 255 0]
[ 0 255 255 255 0]
[ 0 0 0 0 0]
[ 0 0 0 0 0]]
[[1 1]
[1 2]
[2 2]
[3 2]
[3 1]
[2 1]]
Contour points: 6
arcLength: 6.0
我们得到六个轮廓点,两个相邻轮廓点之间的每个“距离”再次为 1,因此轮廓周长(=弧长)也是 6——这似乎(更)合理。
示例 3:2
黑色图像上带有半径的白色圆圈
import cv2
import numpy as np
# Generate 5 x 5 black image
img = np.zeros((5, 5), np.uint8)
# Draw white circle with radius 2
img = cv2.circle(img, (2, 2), 2, 255, cv2.FILLED)
# Find contours
cnts = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0]
# Outputs
print(img, '\n') # Image
print(np.squeeze(cnts[0]), '\n') # Contour
print('Contour points:', cnts[0].shape[0], '\n')
print('arcLength:', cv2.arcLength(cnts[0], True))
输出:
[[ 0 0 255 0 0]
[ 0 255 255 255 0]
[255 255 255 255 255]
[ 0 255 255 255 0]
[ 0 0 255 0 0]]
[[2 0]
[1 1]
[0 2]
[1 3]
[2 4]
[3 3]
[4 2]
[3 1]]
Contour points: 8
arcLength: 11.313708305358887
[2 0]
从to的“距离”[1 1]
是 1.414...(2 的平方根)。每两个相邻的轮廓点都有这个距离(见图),所以我们的轮廓周长(=弧长)为 8 * 1.414... = 11.313...
希望有助于理解!
----------------------------------------
System information
----------------------------------------
Platform: Windows-10-10.0.16299-SP0
Python: 3.8.1
NumPy: 1.18.1
OpenCV: 4.2.0
----------------------------------------
推荐阅读
- mysql - MySQL - UNION 先选择排序
- html - 如何在空白处制作居中下划线?
- java - 自定义倒数计时器 Android Studio
- java - 使用 powermockito 在 Utils 类中存根静态私有方法
- android - 连接到 Google 应用引擎端点时找不到 404
- vector - OL5 VectorTileLayer:瓦片的Y坐标
- php - 如何将文件上传到谷歌驱动器中的特定文件夹-谷歌驱动器 API (PHP)
- string - 在 Visual Studio 中禁用字符串突出显示
- laravel - Laravel Eloquent:从 getAttribute 函数内部获取模型 ID?
- class - 类中的构造函数,什么时候创建对象?