使用vip实现透视转换



我正在尝试在Go中使用vips实现透视转换。我使用opencv的GetPerspectiveTransform方法来计算变换矩阵,然后计算地图图像,如下

func DistortPerspective(ref *vips.ImageRef, tiepoints []float64) {
T := createTransform(tiepoints)
// make an index image where pixels have the value of their (x, y) coordinates
index, err := vips.XYZ(ref.Width(), ref.Height())
if err != nil {
logger.Debug(nil, err)
}
i0, err := index.Copy()
if err != nil {
logger.Debug(nil, err)
}
i1, err := index.Copy()
if err != nil {
logger.Debug(nil, err)
}
err = i0.ExtractBand(0, 1)
if err != nil {
logger.Debug(nil, err)
}
err = i1.ExtractBand(1, 1)
if err != nil {
logger.Debug(nil, err)
}
T00 := float64(T.GetFloatAt(0, 0))
T01 := float64(T.GetFloatAt(0, 1))
T02 := float64(T.GetFloatAt(0, 2))
T10 := float64(T.GetFloatAt(1, 0))
T11 := float64(T.GetFloatAt(1, 1))
T12 := float64(T.GetFloatAt(1, 2))
T20 := float64(T.GetFloatAt(2, 0))
T21 := float64(T.GetFloatAt(2, 1))
T22 := float64(T.GetFloatAt(2, 2))
// i0 * T[0,0]
i0xT00 := linear(i0, T00, 0)
// i1 * T[0,1] + T[0,2]
i1xT01_T02 := linear(i1, T01, T02)
// i0 * T[1,0]
i0xT10 := linear(i0, T10, 0)
// i1 * T[1,1] + T[1,2]
i1xT11_T12 := linear(i1, T11, T12)
//i[0] * T[0,0] + i[1] * T[0,1] + T[0,2]
i0xT00_i1xT01_T02 := add(i0xT00, i1xT01_T02)
//i[0] * T[1,0] + i[1] * T[1,1] + T[1,2]
i0xT10_i1xT11_T12 := add(i0xT10, i1xT11_T12)
//i[0] * T[2,0]
i0xT20 := linear(i0, T20, 0)
//i[1] * T[2,1] + T[2,2]
i1xT21_T22 := linear(i1, T21, T22)
//i[0] * T[2,0] + i[1] * T[2,1] + T[2,2]
i0xT20_i1xT21_T22 := add(i0xT20, i1xT21_T22)
//x = (i[0] * T[0,0] + i[1] * T[0,1] + T[0,2]) / (i[0] * T[2,0] + i[1] * T[2,1] + T[2,2])
x := divide(i0xT00_i1xT01_T02, i0xT20_i1xT21_T22)
//y = (i[0] * T[1,0] + i[1] * T[1,1] + T[1,2]) / (i[0] * T[2,0] + i[1] * T[2,1] + T[2,2])
y := divide(i0xT10_i1xT11_T12, i0xT20_i1xT21_T22)
//# join up x and y as a map image
mapimage := bandjoin(x, y)
//transform the original image
err = ref.Mapim(mapimage)
if err != nil {
logger.Debug(nil, err)
}
}

然而,由此产生的图像是错误的。我用这个Stack Overflow的答案作为参考。如何在VIPS中执行透视扭曲转换?在我看来,opencvWarpPerspective方法也有类似的作用,所以我认为使用opencv来计算变换系数是可行的。

答案是双重的。

首先,使用返回正确float64的GetDoubleAt(row int, col int)方法,而不是返回float32的GetFloatAt(row int, col int)方法。不知怎么的,转换把数字搞砸了。

其次,在计算变换矩阵的方法中,在GetPerspectiveTransform调用中,源集和目的集应该翻转。这是因为opencv的WarpPerspective方法隐式地反转矩阵,而这个实现没有。

func createTransform(distortion []float64) gocv.Mat {
srcSet := []image.Point{
{X: int(distortion[0]), Y: int(distortion[1])},
{X: int(distortion[4]), Y: int(distortion[5])},
{X: int(distortion[8]), Y: int(distortion[9])},
{X: int(distortion[12]), Y: int(distortion[13])},
}
dstSet := []image.Point{
{X: int(distortion[2]), Y: int(distortion[3])},
{X: int(distortion[6]), Y: int(distortion[7])},
{X: int(distortion[10]), Y: int(distortion[11])},
{X: int(distortion[14]), Y: int(distortion[15])},
}
return gocv.GetPerspectiveTransform(dstSet, srcSet)
}

最新更新