112 lines
3.0 KiB
Go
112 lines
3.0 KiB
Go
package main
|
|
|
|
import (
|
|
"image"
|
|
"math"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
"gocv.io/x/gocv"
|
|
)
|
|
|
|
type PhaseShiftM struct {
|
|
dx float32
|
|
dy float32
|
|
Block Block
|
|
}
|
|
|
|
type Block struct {
|
|
width int
|
|
height int
|
|
coord image.Point // top-left corner of the block in the original image
|
|
}
|
|
|
|
func (r *Registrator) calculateBlockPhaseShift(panBlock, mssBlock gocv.Mat) gocv.Point2f {
|
|
pan := gocv.NewMat()
|
|
mss := gocv.NewMat()
|
|
|
|
panBlock.ConvertTo(&pan, gocv.MatTypeCV32FC1)
|
|
defer pan.Close()
|
|
mssBlock.ConvertTo(&mss, gocv.MatTypeCV32FC1)
|
|
defer mss.Close()
|
|
|
|
hann := gocv.NewMat()
|
|
defer hann.Close()
|
|
|
|
shift, response := gocv.PhaseCorrelate(pan, mss, hann)
|
|
|
|
dx := shift.X
|
|
dy := shift.Y
|
|
log.Printf("Block shift: dx = %f, dy = %f. response = %f \n", dx, dy, response)
|
|
|
|
return shift
|
|
}
|
|
|
|
func (r *Registrator) DoMssPhaseShift() ([][]byte, error) {
|
|
alignedMssData := make([][]byte, MssBands)
|
|
// 使用平均偏移量来做平移变换
|
|
for band := 0; band < MssBands; band++ {
|
|
var efficientShiftM int
|
|
var xTotal, yTotal float32
|
|
for _, shift := range r.phaseShifts[band] {
|
|
if math.IsNaN(float64(shift.dx)) || math.IsNaN(float64(shift.dy)) {
|
|
continue
|
|
}
|
|
efficientShiftM += 1
|
|
xTotal += shift.dx
|
|
yTotal += shift.dy
|
|
}
|
|
dx := xTotal / float32(efficientShiftM)
|
|
dy := yTotal / float32(efficientShiftM)
|
|
log.Println("Band", band+1, "average shift:", dx, dy, "efficientShiftM:", efficientShiftM)
|
|
|
|
translationMat := gocv.NewMatWithSize(2, 3, gocv.MatTypeCV32F)
|
|
defer translationMat.Close()
|
|
|
|
translationMat.SetFloatAt(0, 0, 1)
|
|
translationMat.SetFloatAt(0, 1, 0)
|
|
translationMat.SetFloatAt(0, 2, dx)
|
|
translationMat.SetFloatAt(1, 0, 0)
|
|
translationMat.SetFloatAt(1, 1, 1)
|
|
translationMat.SetFloatAt(1, 2, dy)
|
|
|
|
alignedMss := gocv.NewMatWithSize(r.MssHeight, r.MssWidth, gocv.MatTypeCV32FC1)
|
|
defer alignedMss.Close()
|
|
|
|
cvtMss := gocv.NewMat()
|
|
defer cvtMss.Close()
|
|
|
|
r.MssImages[band].ConvertTo(&cvtMss, gocv.MatTypeCV32FC1)
|
|
// 手动平移像素
|
|
outY := math.MaxInt
|
|
for y := 0; y < r.MssHeight; y++ {
|
|
for x := 0; x < r.MssWidth; x++ {
|
|
// 计算新的坐标
|
|
newX := x + int(dx)
|
|
newY := y + int(dy)
|
|
|
|
// 如果新坐标在图像范围内,进行像素值赋值
|
|
if newX >= 0 && newX < r.MssWidth && newY >= 0 && newY < r.MssHeight {
|
|
alignedMss.SetFloatAt(y, x, cvtMss.GetFloatAt(newY, newX))
|
|
} else {
|
|
// 如果新坐标不在图像范围内,设置为黑色
|
|
alignedMss.SetFloatAt(y, x, 0)
|
|
if outY > y {
|
|
outY = y
|
|
log.Println("Warning: pixel out of range", x, y)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// gocv.WarpAffine(cvtMss, &alignedMss, translationMat, image.Pt(cvtMss.Size()[1], cvtMss.Size()[0]))
|
|
r.registeredMssImages[band] = gocv.NewMat()
|
|
alignedMss.ConvertTo(&r.registeredMssImages[band], gocv.MatTypeCV16U)
|
|
|
|
log.Println("Band", band+1, "registeredMssImages size:", r.registeredMssImages[band].Size())
|
|
|
|
alignedMssData[band] = append(alignedMssData[band], r.registeredMssImages[band].ToBytes()...)
|
|
}
|
|
|
|
return alignedMssData, nil
|
|
}
|