- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我想在一个简单的坐标系中实现线检测。我大致遵循了一篇关于如何实现the Hough Transform的文章。 , 但我得到的结果与我想要的相去甚远。
给定一个像这样的 3 x 3 矩阵:
X X X
X X X
- - -
我想检测从 0,0
到 2,0
的行。我将坐标系表示为一个简单的元组数组,元组中的第一项是 x,第二项是 y,第三项是点的类型( Canvas 或线)。
我认为使用 Hough 检测线会相对容易,因为边缘检测基本上只是一个二元决策:元组是否为线类型。
我用 Rust 实现了以下程序:
use std::f32;
extern crate nalgebra as na;
use na::DMatrix;
#[derive(Debug, PartialEq, Clone)]
enum Representation {
Canvas,
Line,
}
fn main () {
let image_width = 3;
let image_height = 3;
let grid = vec![
(0, 0, Representation::Line), (1, 0, Representation::Line), (2, 0, Representation::Line),
(0, 1, Representation::Canvas), (1, 1, Representation::Canvas), (2, 1, Representation::Canvas),
(0, 2, Representation::Canvas), (1, 2, Representation::Canvas), (2, 2, Representation::Canvas),
];
//let tmp:f32 = (image_width as f32 * image_width as f32) + (image_height as f32 * image_height as f32);
let max_line_length = 3;
let mut accumulator = DMatrix::from_element(180, max_line_length as usize, 0);
for y in 0..image_height {
for x in 0..image_width {
let coords_index = (y * image_width) + x;
let coords = grid.get(coords_index as usize).unwrap();
// check if coords is an edge
if coords.2 == Representation::Line {
for angle in 0..180 {
let r = (x as f32) * (angle as f32).cos() + (y as f32) * (angle as f32).sin();
let r_scaled = scale_between(r, 0.0, 2.0, -2.0, 2.0).round() as u32;
accumulator[(angle as usize, r_scaled as usize)] += 1;
}
}
}
}
let threshold = 3;
// z = angle
for z in 0..180 {
for r in 0..3 {
let val = accumulator[(z as usize, r as usize)];
if val < threshold {
continue;
}
let px = (r as f32) * (z as f32).cos();
let py = (r as f32) * (z as f32).sin();
let p1_px = px + (max_line_length as f32) * (z as f32).cos();
let p1_py = py + (max_line_length as f32) * (z as f32).sin();
let p2_px = px - (max_line_length as f32) * (z as f32).cos();
let p2_py = px - (max_line_length as f32) * (z as f32).cos();
println!("Found lines from {}/{} to {}/{}", p1_px.ceil(), p1_py.ceil(), p2_px.ceil(), p2_py.ceil());
}
}
}
fn scale_between(unscaled_num: f32, min_allowed: f32, max_allowed: f32, min: f32, max: f32) -> f32 {
(max_allowed - min_allowed) * (unscaled_num - min) / (max - min) + min_allowed
}
结果是这样的:
Found lines from -1/4 to 1/1
Found lines from 2/4 to 0/0
Found lines from 2/-3 to 0/0
Found lines from -1/4 to 1/1
Found lines from 1/-3 to 0/0
Found lines from 0/4 to 1/1
...
这实际上很多,因为我只想检测一条线。我的实现显然是错误的,但我不知道从哪里看,我的数学功底还不够高,无法进一步调试。
我认为第一部分,即实际的霍夫变换,似乎有点正确,因为链接的文章说:
for each image point p
{
if (p is part of an edge)
{
for each possible angle
{
r = x * cos(angle) + y * sin(angle);
houghMatrix[angle][r]++;
}
}
}
我被困在映射和过滤上,这是根据文章:
Each point in Hough space is given by angle a and distance r. Using these values, one single point p(x,y) of the line can be calculated by px = r * cos(angle) py = r * sin(angle).
The maximum length of a line is restricted by sqrt(imagewidth2 + imageheight2).
The point p, the angle a of the line and the maximum line length 'maxLength' can be used to calculate two other points of the line. The maximum length here ensures that both points to be calculated are lying outside of the actual image, resulting in the fact that if a line is drawn between these two points, the line goes from image border to image border in any case and is never cropped somewhere inside the image.
These two points p1 and p2 are calculated by: p1_x = px + maxLength * cos(angle); p1_y = py + maxLength * sin(angle); p2_x = px - maxLength * cos(angle); p2_y = py - maxLength * sin(angle);
...
编辑
根据@RaymoAisla 的建议,更新版本考虑了图像大小
use std::f32;
extern crate nalgebra as na;
use na::DMatrix;
fn main () {
let image_width = 3;
let image_height = 3;
let mut grid = DMatrix::from_element(image_width as usize, image_height as usize, 0);
grid[(0, 0)] = 1;
grid[(1, 0)] = 1;
grid[(2, 0)] = 1;
let accu_width = 7;
let accu_height = 3;
let max_line_length = 3;
let mut accumulator = DMatrix::from_element(accu_width as usize, accu_height as usize, 0);
for y in 0..image_height {
for x in 0..image_width {
let coords = (x, y);
let is_edge = grid[coords] == 1;
if !is_edge {
continue;
}
for i in 0..7 {
let angle = i * 30;
let r = (x as f32) * (angle as f32).cos() + (y as f32) * (angle as f32).sin();
let r_scaled = scale_between(r, 0.0, 2.0, -2.0, 2.0).round() as u32;
accumulator[(i as usize, r_scaled as usize)] += 1;
println!("angle: {}, r: {}, r_scaled: {}", angle, r, r_scaled);
}
}
}
let threshold = 3;
// z = angle index
for z in 0..7 {
for r in 0..3 {
let val = accumulator[(z as usize, r as usize)];
if val < threshold {
continue;
}
let px = (r as f32) * (z as f32).cos();
let py = (r as f32) * (z as f32).sin();
let p1_px = px + (max_line_length as f32) * (z as f32).cos();
let p1_py = py + (max_line_length as f32) * (z as f32).sin();
let p2_px = px - (max_line_length as f32) * (z as f32).cos();
let p2_py = px - (max_line_length as f32) * (z as f32).cos();
println!("Found lines from {}/{} to {}/{} - val: {}", p1_px.ceil(), p1_py.ceil(), p2_px.ceil(), p2_py.ceil(), val);
}
}
}
fn scale_between(unscaled_num: f32, min_allowed: f32, max_allowed: f32, min: f32, max: f32) -> f32 {
(max_allowed - min_allowed) * (unscaled_num - min) / (max - min) + min_allowed
}
现在报告的输出是:
angle: 0, r: 0, r_scaled: 1
angle: 30, r: 0, r_scaled: 1
angle: 60, r: 0, r_scaled: 1
angle: 90, r: 0, r_scaled: 1
angle: 120, r: 0, r_scaled: 1
angle: 150, r: 0, r_scaled: 1
angle: 180, r: 0, r_scaled: 1
...
Found lines from 3/4 to -1/-1
Found lines from -3/1 to 2/2
我在坐标系上绘制了线条,这些线条与我期望的线条相距甚远。我想知道转换回积分是否仍然关闭。
最佳答案
你的角度是度数而不是Arc度!
与所有其他编程语言一样,Rust 的三角函数使用Arc度。运行
let ang_d = 30.0;
let ang_r = ang_d * 3.1415926 / 180.0;
println!("sin(30) {} sin(30*pi/180) {}", (ang_d as f32).sin(), (ang_r as f32).sin());
给出结果
sin(30) -0.9880316 sin(30*pi/180) 0.5
在调用 cos
和 sin
之前,您需要将所有角度转换为Arc度。
在第一个循环中我得到了
let angle = (i as f32) * 30.0 * 3.1415926 / 180.0;
let r = (x as f32) * (angle as f32).cos() + (y as f32) * (angle as f32).sin();
在第二个地方你计算线上的点
let ang = (z as f32) * 30.0 * 3.1415926 / 180.0;
let px = (r as f32) * (ang as f32).cos();
let py = (r as f32) * (ang as f32).sin();
let p1_px = px + (max_line_length as f32) * (ang as f32).cos();
let p1_py = py + (max_line_length as f32) * (ang as f32).sin();
let p2_px = px - (max_line_length as f32) * (ang as f32).cos();
let p2_py = px - (max_line_length as f32) * (ang as f32).cos();
我的 Rust 使用rust 了(实际上不存在),所以有更好的方法来进行转换,并且应该有一个常数,在某处具有 pi 的精确值。
关于algorithm - 在二维坐标系下实现霍夫变换直线检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40479958/
我一直在试图弄清楚小部件的坐标是如何到达的。例如在 qt 文档中,我想知道这是如何完成的。 QGridLayout *layout = new QGridLayout; layout->ad
我正在尝试在 libGDX 中正确配置我的 Camera 和 Sprite,以正确显示在 2D 坐标系中,原点位于左下角。 我像这样设置我的相机: cameraWidth = Gdx.graphics
我最近查看了 App Store 中提供的 Swift Playgrounds 应用程序,在那里我偶然发现了这个交互式坐标系 View ,类似于可以在 Mac 上的 Xcode playgrounds
我知道 Posit 会计算相机和 3d 对象之间的平移和旋转。我现在唯一的问题是,我不知道相机和物体的坐标系是如何定义的。因此,例如,如果我绕 z 轴旋转 90°,z 轴指向哪个方向,物体是绕这个轴旋
我想完成以下事情。我有一组PDF文件,首先我想检查坐标系的原点。如果 pdf 坐标系的原点不是左上角 [通常原点在左下角],我想创建一个坐标在左上角的结果 PDF。我正在尝试使用 PDFBox [下面
我有来自 AVAsset 的 CVPixelBufferRef。我正在尝试对其应用 CIFilter。我使用这些行: CVPixelBufferRef pixelBuffer = ... CVPixe
我很难理解 OpenLayers 使用的坐标系。 英国莱斯特大约在。 Latitude: 52.63973017532399 Longitude: -1.142578125 但要使用 OpenLay
我刚开始iOS绘图编程,发现坐标系和Mac OS X不同,基本上iOS上的原点在左上角,而不是像Mac上的左下角。只是想知道是否有人知道 Apple 为何做出此更改,以及 Mac 的 future 也
我想更改 PDF 坐标系以更改原点 (0,0) -> 从左下角到左上角。因此,例如,当我在 x=5 y=10 的位置书写文本时,它将以从左数起 10 点和从上数(而不是从下数)开始的 10 点书写。
我有以下代码: QGraphicsScene* pScene = new QGraphicsScene(this); ui->graphicsView->setScene(pScene); pScen
我目前正在尝试实现一个基于室内地图的 AR 浏览器,但我面临几个问题,让我们看一下图: 在这个图中,我已经将坐标更改为OpenGL的右手坐标系。 在我们的真实场景中, 给定角度 FOV/2 和相机高度
我正在尝试在 ios 中构建自定义 warp 内核。 我有这个内核代码 var kernelCode = " kernel vec2 partialFlip(vec2 center,
我在我的旧手机 (Samsung Galaxy Ace) 上测试我的“游戏”,我把它给了我妈妈,所以我现在使用的是平板电脑 (Samsung GT-P7300),但我在当我触摸屏幕时的坐标。我在 An
我正在开发一个网络应用程序,它包括一个我绘制函数图形的部分,坐标系是由 Canvas 制作的。问题是,我无法放大坐标系。我想让它能够放大和缩小+使用鼠标移动坐标系。放大/缩小时,x 和 y 值也应该增
我的问题类似于Changing sensor coordinate system in android 无论设备方向如何,我都希望能够相互比较用户的 Action 。因此,当用户以纵向握住手机并弯曲
我正在尝试使用 stereoRectify。我没有使用 stereoCalibrate 校准我的相机,而是已经有了一些信息,我将使用这些信息来创建相机矩阵,这些矩阵是 stereoRectify 的输
我在矩阵中有一个对象的足迹,简而言之,对象占用了哪些单元格(对象是一个部分,标记为 0 的单元格未被占用,标记为 1 的单元格被对象占用)。然后,我在 list > 中有一个已占用单元格的列表。与矩阵
我是 Canvas 的新手,想知道: 使用倒笛卡尔坐标系的基本原理。 比如说,我需要在直方图中绘制一些值。是一种将 Canvas 框架旋转/映射到笛卡尔坐标系的简单方法。? 最佳答案 Canvas 是
通读 SVG 1.1 specification ,我试图了解用于定义初始视口(viewport)的单位与文档其余部分使用的单位之间的关系。 如果视口(viewport)最初是使用点定义的 并且文档
好的,所以我找到了这个 thread ,这是我认为我需要做的。但是,我使用的不是 GL10,而是 GLES20。 glOrthof 不是 GLES20 API 的一部分。 我想做的是改变坐标系的范围,
我是一名优秀的程序员,十分优秀!