图像中的像素插值,我也是在canny中学会的,比如我们旋转后的线图像,个个都是插值而成的,你可以看一看前面的博文,诸如此类:
if (k > -1 && k <= 0)
{
float avgGrey = (float)buffer8[(int)j * wh.Width + i];
float avgGrey1 = (float)buffer8[((int)j + 1) * wh.Width + i];
grey = avgGrey * (1 - tempf) + avgGrey1 * tempf;
}
else
{
float avgGrey = (float)buffer8[(int)j * wh.Width + i];
float avgGrey1 = (float)buffer8[((int)j - 1) * wh.Width + i];
grey = avgGrey * (1 - tempf) + avgGrey1 * tempf;
}
我们的这一节,主要针对非极大值抑制,这是一个很响亮的名字,他里边就使用了很多这种插值,其实所谓插值,浮点像素呗!这就是所谓的亚像素。(需要提高精度,必须如此!)
上面代码的意思是说:看图
假定a=buffer(i,j-1);b=buffer(i,j),c=buffer(i,j+1);a,b(avgGrey),c(avgGrey1)为灰度;A,B,C为三个点。
那么 (k > -1 && k <= 0),直线x=-y就会由B偏向C,假定偏移了0.3=tempf,则,直线x=-y倾斜后与BC相交点的灰度值grey=0.3*c++0.7*b=avgGrey * (1 - tempf) + avgGrey1 * tempf;
相反,(k>-1),直线就会与AB相交,则同理,仍有 grey = avgGrey * (1 - tempf) + avgGrey1 * tempf;
以上,虽然是笛卡尔数学坐标系,但在图像坐标系更好理解。
那么,非极大值抑制也有一段这样的代码:
c=观察中心///
/ g3 /
/ g4 C g2 /
/ g1 /
/
else if (((m_Theta[j, i] >= 135) && (m_Theta[j, i] < 180)) ||
((m_Theta[j, i] >= 315) && (m_Theta[j, i] < 360)))
{ //int nPointIdx = i+j*w;
g1 = m_M[j + 1, i + 1];
g2 = m_M[j, i + 1];
g3 = m_M[j - 1, i - 1];
g4 = m_M[j, i - 1];
dWeight = Math.Abs(m_Q[j, i] / (m_P[j, i] * 1.0)); //タち
dTmp1 = g1 * dWeight + g2 * (1 - dWeight);
dTmp2 = g3 * dWeight + g4 * (1 - dWeight);
}
对照图,就会很好理解。
需要说明的是,这条线是穿越点c的梯度方向,重复以下强调过的概念,穿越点c的梯度方向垂直于边缘,当前c的梯度幅值最大,但求出g1g2之间的亚像素点c1的梯度幅值大于c(边缘过c1),或者g3g4之间的亚像素点c2的梯度幅值大于c(边缘过c2),则c点会被舍弃,因为他不在边缘上,而边缘可能在c1上,或在c2上(边缘的定位精度提高了)。
这就是鼎鼎有名的,非极大值抑制,为什么是这样?因为,我们的像素点是整型的,这里引入了亚像素概念,提高了认知精度,仅此而已。
以上只是一个片段,因为你至少应该处理四个方向,剩下的只有重复。