Files
sjy01-image-proc/pkg/producer/scenes.go
2024-06-09 20:08:32 +08:00

224 lines
6.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package producer
import (
"encoding/json"
"fmt"
"image"
"os"
"path/filepath"
"strings"
"github.com/airbusgeo/godal"
"github.com/paulmach/orb"
"github.com/paulmach/orb/geojson"
log "github.com/sirupsen/logrus"
"gocv.io/x/gocv"
)
type Scene struct {
Type string
Width int
Height int
X int // coordinate of the left top corner of the scene
Y int
Mat []gocv.Mat
Tiff string
Meta *ProductMeta
SceneId string
}
func (s *Scene) Cleanup() {
for i := range s.Mat {
s.Mat[i].Close()
}
}
// 对 PAN 和 配准后的MSS 在 Y 方向进行分景景之间有25%的重叠
// 默认分景大小:
// MSS 2336 * 2336 - 1764
// PAN 9344 * 9344 - 7056
func (r *Registrator) SubScenes() (panScenes []*Scene, mssScenes []*Scene, err error) {
hPAN := (9344 - 2336)
hPANOverlap := 2336
panScenesCnt := r.PanHeight / hPAN
for i := 0; i < panScenesCnt; i++ {
y1 := (i+1)*hPAN + hPANOverlap
if y1 > r.PanHeight {
y1 = r.PanHeight
}
scene := &Scene{
Type: "PAN",
Width: 9344,
Height: y1 - i*hPAN,
X: 0,
Y: i * hPAN,
}
name := filepath.Base(r.Params.PanTiffFile)
name = strings.TrimSuffix(name, ".tiff")
scene.SceneId = fmt.Sprintf("%s_%03d", name, i+1)
mat := r.PanImage.Region(image.Rect(0, i*hPAN, 9344, y1))
scene.Mat = append(scene.Mat, mat)
panScenes = append(panScenes, scene)
}
hMSS := hPAN / 4
hMSSOverlap := hPANOverlap / 4
mssScenesCnt := r.MssHeight / hMSS
for i := 0; i < mssScenesCnt; i++ {
y1 := (i+1)*hMSS + hMSSOverlap
if y1 > r.MssHeight {
y1 = r.MssHeight
}
scene := &Scene{
Type: "MSS",
Width: 2336,
Height: y1 - i*hMSS,
X: 0,
Y: i * hMSS,
}
for band := 0; band < 4; band++ {
mat := r.registeredMssImages[band].Region(image.Rect(0, i*hMSS, 2336, y1))
scene.Mat = append(scene.Mat, mat)
}
name := filepath.Base(r.Params.MssTiffFile)
name = strings.TrimSuffix(name, ".tiff")
scene.SceneId = fmt.Sprintf("%s_%03d", name, i+1)
mssScenes = append(mssScenes, scene)
}
if len(panScenes) != len(mssScenes) {
log.Error("pan and mss scenes count not match")
err = fmt.Errorf("pan and mss scenes count not match")
}
return panScenes, mssScenes, err
}
func (r *Registrator) SaveScenesToTiff(panScenes []*Scene, mssScenes []*Scene) error {
var fc geojson.FeatureCollection
for i, scene := range panScenes {
dir := filepath.Join(r.Params.OutputDir, fmt.Sprintf("%03d", i+1), "PAN")
os.MkdirAll(dir, 0755)
filename := fmt.Sprintf("%s_L1A.tiff", scene.SceneId)
scene.Tiff = filepath.Join(dir, filename)
scene.Meta = r.makeProductMeta(scene)
r.SetSceneBoundary(scene)
err := savePanToGDALGTiff(scene.Mat[0],
scene.Meta.Corners.UpperLeft.Longitude,
scene.Meta.Corners.UpperLeft.Latitude,
scene.Tiff,
scene.Meta.Gsd)
if err != nil {
log.Errorf("save pan scene %d to tiff failed: %v", i+1, err)
return err
}
scene.Meta.DataSize = sizeOfFile(scene.Tiff)
metaFile := strings.Replace(scene.Tiff, ".tiff", ".meta.xml", 1)
r.writeProductMeta(scene.Meta, metaFile)
jpg := strings.Replace(scene.Tiff, ".tiff", ".jpg", 1)
GTiffToJPG(scene.Tiff, jpg, false)
r.report.Scenes = append(r.report.Scenes, ReportScene{
Name: scene.SceneId,
TiffData: scene.Tiff,
MetaData: metaFile,
BrowserData: jpg,
})
feature := geojson.NewFeature(orb.Polygon{
{
{scene.Meta.Corners.UpperLeft.Longitude, scene.Meta.Corners.UpperLeft.Latitude},
{scene.Meta.Corners.UpperRight.Longitude, scene.Meta.Corners.UpperRight.Latitude},
{scene.Meta.Corners.LowerRight.Longitude, scene.Meta.Corners.LowerRight.Latitude},
{scene.Meta.Corners.LowerLeft.Longitude, scene.Meta.Corners.LowerLeft.Latitude},
{scene.Meta.Corners.UpperLeft.Longitude, scene.Meta.Corners.UpperLeft.Latitude},
},
})
fc.Features = append(fc.Features, feature)
}
data, _ := json.Marshal(fc)
// 输出 GeoJSON 数据
log.Debug(string(data))
for i, scene := range mssScenes {
dir := filepath.Join(r.Params.OutputDir, fmt.Sprintf("%03d", i+1), "MSS")
os.MkdirAll(dir, 0755)
filename := fmt.Sprintf("%s_L1A.tiff", scene.SceneId)
scene.Tiff = filepath.Join(dir, filename)
scene.Meta = r.makeProductMeta(scene)
r.SetSceneBoundary(scene)
rgbirImage, _ := r.MergeMSSToBGRNIR(scene.Mat)
err := SaveBGRToGDALGTiff(rgbirImage,
4,
scene.Meta.Corners.UpperLeft.Longitude,
scene.Meta.Corners.UpperLeft.Latitude,
scene.Meta.Gsd,
[]godal.ColorInterp{godal.CIBlue, godal.CIGreen, godal.CIRed, godal.CIUndefined},
scene.Tiff)
if err != nil {
log.Errorf("save mss scene %d to tiff failed: %v", i+1, err)
return err
}
scene.Meta.DataSize = sizeOfFile(scene.Tiff)
metaFile := strings.Replace(scene.Tiff, ".tiff", ".meta.xml", 1)
r.writeProductMeta(scene.Meta, metaFile)
jpg := strings.Replace(scene.Tiff, ".tiff", ".jpg", 1)
GTiffToJPG(scene.Tiff, jpg, false)
r.report.Scenes = append(r.report.Scenes, ReportScene{
Name: scene.SceneId,
TiffData: scene.Tiff,
MetaData: metaFile,
BrowserData: jpg,
})
}
return nil
}
func (r *Registrator) DoScenePansharpen(panScenes []*Scene, mssScenes []*Scene) error {
for i := 0; i < len(panScenes); i++ {
fusedTiff := strings.Replace(mssScenes[i].Tiff, "MSS", "FUS", -1)
err := GDALPansharpen(panScenes[i].Tiff, mssScenes[i].Tiff, fusedTiff)
if err != nil {
return err
}
jpg := strings.Replace(fusedTiff, ".tiff", ".jpg", 1)
GTiffToJPG(fusedTiff, jpg, true)
r.report.Scenes = append(r.report.Scenes, ReportScene{
TiffData: fusedTiff,
Name: strings.TrimSuffix(filepath.Base(fusedTiff), ".tiff"),
BrowserData: jpg,
})
}
return nil
}
func (r *Registrator) MergeMSSToBGRNIR(channels []gocv.Mat) (gocv.Mat, error) {
var rgbirImage gocv.Mat
if len(channels) != 4 {
return rgbirImage, fmt.Errorf("mss channels count not match")
}
rgbirImage = gocv.NewMat()
gocv.Merge(channels, &rgbirImage)
log.Printf("merge mss to bgr nir image, channels: %d, height: %d, width: %d",
rgbirImage.Channels(), rgbirImage.Rows(), rgbirImage.Cols())
return rgbirImage, nil
}