我试图在高空拍摄的图像中探测地平线,以便确定相机的方位。我也在试着让它运行的更快-理想的情况下,我希望能够实时处理帧(也就是说,每秒几帧)。到目前为止,我所采用的方法是基于这样一个事实:在高海拔地区,天空非常黑暗,如下所示:
我所做的就是从整个图像中提取样本,并将它们分为明暗两类,然后在它们之间划出一条线。然而,由于地平线上的模糊位置:
下面是我的代码(为了便于web演示,我用Javascript编写):
function mag(arr) {
return Math.sqrt(arr[0]*arr[0]+arr[1]*arr[1]+arr[2]*arr[2])
}
// return (a, b) that minimize
// sum_i r_i * (a*x_i+b - y_i)^2
function linear_regression( xy ) {
var i,
x, y,
sumx=0, sumy=0, sumx2=0, sumy2=0, sumxy=0, sumr=0,
a, b;
for(i=0;i<xy.length;i++) {
x = xy[i][0]; y = xy[i][2];
r = 1
sumr += r;
sumx += r*x;
sumx2 += r*(x*x);
sumy += r*y;
sumy2 += r*(y*y);
sumxy += r*(x*y);
}
b = (sumy*sumx2 - sumx*sumxy)/(sumr*sumx2-sumx*sumx);
a = (sumr*sumxy - sumx*sumy)/(sumr*sumx2-sumx*sumx);
return [a, b];
}
var vals = []
for (var i=0; i<resolution; i++) {
vals.push([])
for (var j=0; j<resolution; j++) {
x = (canvas.width/(resolution+1))*(i+0.5)
y = (canvas.height/(resolution+1))*(j+0.5)
var pixelData = cr.getImageData(x, y, 1, 1).data;
vals[vals.length-1].push([x,y,pixelData])
cr.fillStyle="rgb("+pixelData[0]+","+pixelData[1]+","+pixelData[2]+")"
cr.strokeStyle="rgb(255,255,255)"
cr.beginPath()
cr.arc(x,y,10,0,2*Math.PI)
cr.fill()
cr.stroke()
}
}
var line1 = []
var line2 = []
for (var i in vals) {
i = parseInt(i)
for (var j in vals[i]) {
j = parseInt(j)
if (mag(vals[i][j][3])<minmag) {
if ((i<(vals.length-2) ? mag(vals[i+1][j][4])>minmag : false)
|| (i>0 ? mag(vals[i-1][j][5])>minmag : false)
|| (j<(vals[i].length-2) ? mag(vals[i][j+1][6])>minmag : false)
|| (j>0 ? mag(vals[i][j-1][7])>minmag : false)) {
cr.strokeStyle="rgb(255,0,0)"
cr.beginPath()
cr.arc(vals[i][j][0],vals[i][j][8],10,0,2*Math.PI)
cr.stroke()
line1.push(vals[i][j])
}
}
else if (mag(vals[i][j][9])>minmag) {
if ((i<(vals.length-2) ? mag(vals[i+1][j][10])<minmag : false)
|| (i>0 ? mag(vals[i-1][j][11])<minmag : false)
|| (j<(vals[i].length-2) ? mag(vals[i][j+1][12])<minmag : false)
|| (j>0 ? mag(vals[i][j-1][13])<minmag : false)) {
cr.strokeStyle="rgb(0,0,255)"
cr.beginPath()
cr.arc(vals[i][j][0],vals[i][j][14],10,0,2*Math.PI)
cr.stroke()
line2.push(vals[i][j])
}
}
}
}
eq1 = linear_regression(line1)
cr.strokeStyle = "rgb(255,0,0)"
cr.beginPath()
cr.moveTo(0,eq1[1])
cr.lineTo(canvas.width,canvas.width*eq1[0]+eq1[1])
cr.stroke()
eq2 = linear_regression(line2)
cr.strokeStyle = "rgb(0,0,255)"
cr.beginPath()
cr.moveTo(0,eq2[1])
cr.lineTo(canvas.width,canvas.width*eq2[0]+eq2[1])
cr.stroke()
eq3 = [(eq1[0]+eq2[0])/2,(eq1[1]+eq2[1])/2]
cr.strokeStyle = "rgb(0,255,0)"
cr.beginPath()
cr.moveTo(0,eq3[1])
cr.lineTo(canvas.width,canvas.width*eq3[0]+eq3[1])
cr.stroke()
以及结果(绿线是检测到的地平线,红色和蓝色是在边界外估计的):
我该如何改进?有没有更有效的方法?最后的程序可能会用Python编写,如果太慢的话,也可以用C编写。
考虑一些基本的通道混合和阈值设置,然后按照@Spektre的建议进行垂直采样。[根据@Spektre的评论,编辑后改为2*R-B而不是R+G-B]
以下是通道混音的一些选项:
看起来#4是最清晰的地平线(感谢@Spektre让我更仔细地检查),将颜色按一定比例混合[红2:绿0:蓝-1],您可以得到这张单色图像:
设置蓝色负片意味着地平线上的蓝色薄雾用来消除那里的模糊。结果证明,这比只使用红色和/或绿色更有效(在GIMP中使用通道混频器试试)。在
然后我们可以进一步澄清,如果您愿意,通过阈值(虽然您可以在采样后这样做),这里是25%灰色:
使用Spektre的垂直采样方法,只需向下扫描,直到看到数值超过25%。对于3条直线,您应该获得3个x,y对,从而重建曲线,知道它是一条抛物线。在
为了获得更好的稳健性,取3个以上的样本并丢弃离群值。在
我会这样做:
转换为BW
像这样从两边扫描水平线和垂直线
垂直线从顶部扫描
黑线显示线的位置。对于选定的一个,绿色箭头显示扫描方向(向下)和颜色强度可视化方向(右侧)。白色曲线是颜色强度图(因此您可以实际看到发生了什么)
int p[];
以存储行预处理每条线
p[0]
是线的第一个像素的强度p[1,...]
对于H
是通过x
派生的,对于V
行,由{模糊
p[1,...]
几次,以避免噪声问题(从两侧来避免位置偏移)。扫描+整合回来
积分只是求和
c(i)=p[ 0 ] + p[ 1 ] + ... + p[ i ]
。如果c
低于treshold,那么你就在大气层外,所以开始扫描,如果从行首开始是这个区域,你就从右边开始扫描。记住你到达tresholdA-point
的地方,继续扫描,直到你到达峰值C-point
(第一个负导数值或实际峰值。。。局部最大值)。计算
B-point
为了简单起见,你可以做}的导数,并从中确定指数函数。如果派生开始与它不同,则您到达了
B = 0.5*(A+C)
,但是如果你想精确的话,那么大气强度是指数增长的,所以扫描从A
到{B-point
,因此请记住所有B-points
(对于每一行)。现在你有了
B-points
所以删除所有无效的
B-points
(每行应该有2个。。。所以大气更大的区域通常是正确的,除非你看到一些黑暗的无缝的近距离物体。通过剩余的
B-points
[注意事项]
你不能根据高度改变
B-point
的位置,因为大气的可视厚度也取决于观察者和光源(太阳)的位置。另外,你应该过滤掉剩余的B-points
,因为在视图中的一些恒星可能会造成混乱。但我认为曲线近似应该足够了。在[Edit1]做了一些有趣的事情
<>我在2006,C++ +vc><强>中做了。因此,您必须更改对环境的映像访问输入图像是
pic0
,输出图像是pic1
它们是我的类,因此一些成员是:xs,ys
图像的像素大小p[y][x].dd
是位于(x,y)
位置的像素,为32位整数类型bmp
是GDI位图rgb2i()
将所有RGB像素转换为强度整数值<0-765>
(r+g+b)
如您所见,所有地平线点都在
pnt[pnts]
数组中,其中:x,y
是地平线点的位置l
是大气厚度(指数部分)id
是识别扫描方向的{ 0,1,2,3 }
这是输出图像(即使是旋转图像也能很好地工作)
这将不适用于太阳辉光图像,除非你添加一些重负荷过滤
相关问题 更多 >
编程相关推荐