do not use IHS

This commit is contained in:
nuknal
2024-05-28 15:15:53 +08:00
parent 538fb71110
commit 5eb5ae6a72
12 changed files with 346 additions and 46 deletions

1
.gitignore vendored
View File

@@ -6,3 +6,4 @@ data
*.png
*.PNG
bin
log

View File

@@ -1,18 +1,5 @@
package main
import (
"github.com/sirupsen/logrus"
)
func init() {
logrus.SetFormatter(&logrus.TextFormatter{
ForceColors: true,
DisableColors: false,
TimestampFormat: "2006-01-02 15:04:05",
FullTimestamp: true,
})
}
func main() {
rootCmd.Execute()
}

View File

@@ -6,17 +6,13 @@ import (
"strings"
"github.com/airbusgeo/godal"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
imageproc "starwiz.cn/sjy01/image-proc"
)
var (
PanRawFile string
MssRawFile string
AuxRawFile string
SaveRegisteredMssRaw bool
PansharpenIHS bool
OutputDir string
params imageproc.Params
)
var procCmd = &cobra.Command{
@@ -25,20 +21,9 @@ var procCmd = &cobra.Command{
Long: `process images`,
Run: func(cmd *cobra.Command, args []string) {
reg := imageproc.NewRegistrator(imageproc.DownSampled)
reg.Params = imageproc.Params{
PanRawFile: PanRawFile,
MssRawFile: MssRawFile,
AuxRawFile: AuxRawFile,
SaveRegisteredMssRaw: SaveRegisteredMssRaw,
PansharpenIHS: PansharpenIHS,
OutputDir: OutputDir,
MssTiffFile: filepath.Join(OutputDir,
strings.TrimSuffix(filepath.Base(MssRawFile),
filepath.Ext(MssRawFile))+".tiff"),
PanTiffFile: filepath.Join(OutputDir,
strings.TrimSuffix(filepath.Base(PanRawFile),
filepath.Ext(PanRawFile))+".tiff"),
}
reg.Params = params
reg.Params.MssTiffFile = filepath.Join(params.OutputDir, strings.TrimSuffix(filepath.Base(params.MssRawFile), filepath.Ext(params.MssRawFile))+".tiff")
reg.Params.PanTiffFile = filepath.Join(params.OutputDir, strings.TrimSuffix(filepath.Base(params.PanRawFile), filepath.Ext(params.PanRawFile))+".tiff")
reg.Params.FusTIffFile = strings.Replace(reg.Params.MssTiffFile, ".tiff", "_FUS.tiff", 1)
if err := reg.LoadMssRaw(); err != nil {
@@ -50,26 +35,32 @@ var procCmd = &cobra.Command{
}
godal.RegisterAll()
os.MkdirAll(OutputDir, 0755)
os.MkdirAll(params.OutputDir, 0755)
if err := reg.DoPhaseCorrelation(); err != nil {
panic(err)
}
reg.DoCoRegestration()
if SaveRegisteredMssRaw {
if params.SaveRegisteredMssRaw {
registerdMSSRAW := filepath.Join(
OutputDir,
strings.TrimSuffix(filepath.Base(MssRawFile), filepath.Ext(MssRawFile))+"_registered.RAW",
params.OutputDir,
strings.TrimSuffix(filepath.Base(params.MssRawFile), filepath.Ext(params.MssRawFile))+"_registered.RAW",
)
reg.SaveRegisteredMssToRaw(registerdMSSRAW)
}
panScenes, mssScenes, err := reg.SubScenes()
if err != nil {
log.Error(err)
}
reg.SaveScenesToTiff(panScenes, mssScenes)
reg.SaveOriginalPanToGDALGTiff(reg.Params.PanTiffFile)
reg.SaveRegisteredMssToGDALGTiff(reg.Params.MssTiffFile)
if PansharpenIHS {
reg.SavePansharpenedToGDALGTiff(reg.Params.FusTIffFile)
if params.PansharpenIHS {
reg.DoScenePansharpen(panScenes, mssScenes)
}
reg.Clean()
@@ -79,10 +70,11 @@ var procCmd = &cobra.Command{
func init() {
rootCmd.AddCommand(procCmd)
procCmd.Flags().StringVarP(&PanRawFile, "pan", "p", "pan.raw", "PAN image raw file path")
procCmd.Flags().StringVarP(&MssRawFile, "mss", "m", "mss.raw", "MSS image raw file path")
procCmd.Flags().StringVarP(&AuxRawFile, "aux", "a", "pms.aux", "AUX image raw file path")
procCmd.Flags().BoolVarP(&SaveRegisteredMssRaw, "srmss", "s", false, "save registered MSS image raw file")
procCmd.Flags().BoolVarP(&PansharpenIHS, "fus", "", false, "pansharpen using IHS")
procCmd.Flags().StringVarP(&OutputDir, "output-dir", "o", "data", "output directory")
procCmd.Flags().StringVarP(&params.PanRawFile, "pan", "p", "pan.raw", "PAN image raw file path")
procCmd.Flags().StringVarP(&params.MssRawFile, "mss", "m", "mss.raw", "MSS image raw file path")
procCmd.Flags().StringVarP(&params.AuxRawFile, "aux", "a", "pms.aux", "AUX image raw file path")
procCmd.Flags().BoolVarP(&params.SaveRegisteredMssRaw, "srmss", "s", false, "save registered MSS image raw file")
procCmd.Flags().BoolVarP(&params.PansharpenIHS, "fus", "", false, "pansharpen using IHS")
procCmd.Flags().StringVarP(&params.OutputDir, "output-dir", "o", "data", "output directory")
procCmd.Flags().BoolVarP(&params.SubScenes, "sub-scenes", "", false, "process sub-scenes")
}

View File

@@ -2,6 +2,9 @@ package imageproc
import (
"image"
"os"
"os/exec"
"strings"
log "github.com/sirupsen/logrus"
@@ -78,3 +81,33 @@ func PansharpenIHS(panImage, mssImage gocv.Mat) gocv.Mat {
return fused16U
}
func GDALPansharpen(panTiff, mssTiff string) (string, error) {
fusedTIff := strings.Replace(mssTiff, "MSS", "FUS", 1)
// pansharpenCmd := exec.Command("gdal_pansharpen.py", "-w 0.6 -w 0.1 -w 0.3 -w 0 -b 3 -b 2 -b 1", panTiff, mssTiff, fusedTIff, "-r cubic", "-of GTiff")
pansharpenCmd := exec.Command("gdal_pansharpen.py",
"-w", "0.6", "-w", "0.1", "-w", "0.3", "-w", "0",
"-b", "3", "-b", "2", "-b", "1",
"-r", "cubic", "-of", "GTiff",
panTiff,
mssTiff,
fusedTIff)
log.Println("Run Command: ", pansharpenCmd.String())
pansharpenCmd.Stdout = os.Stdout
pansharpenCmd.Stderr = os.Stderr
return fusedTIff, pansharpenCmd.Run()
}
func GDALTranslate(srcTiff, dstJPG string) error {
if dstJPG == "" {
dstJPG = strings.TrimSuffix(srcTiff, ".tiff") + ".jpg"
}
// gdal_translate -of JPEG -outsize 50% 50% -r bilinear input.tif output.jpg
cmd := exec.Command("gdal_translate", "-of", "JPEG",
"-scale",
srcTiff, dstJPG)
log.Println("Run Command: ", cmd.String())
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}

13
gdal_pansharpen_test.go Normal file
View File

@@ -0,0 +1,13 @@
package imageproc
import "testing"
func TestGDALPansharpen(t *testing.T) {
// err := GDALPansharpen("data/052022/SJY01_PAN_20240520_115428_052022_103_010.tiff",
// "data/052022/SJY01_MSS_20240520_115428_052022_103_010.tiff")
// if err != nil {
// t.Error(err)
// }
GDALTranslate("data/052022/SJY01_MSS_20240520_115428_052022_103_010_FUS.tiff", "")
}

8
go.mod
View File

@@ -10,16 +10,24 @@ require (
require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/lestrrat-go/strftime v1.0.6 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/term v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
)
require (
github.com/google/go-cmp v0.6.0 // indirect
github.com/k0kubun/pp/v3 v3.2.0
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5
github.com/spf13/cobra v1.8.0
github.com/x-cray/logrus-prefixed-formatter v0.5.2
golang.org/x/net v0.25.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.20.0 // indirect

15
go.sum
View File

@@ -1059,6 +1059,11 @@ github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NB
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4=
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA=
github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205AhTIGQQ=
github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw=
github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA=
github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o=
@@ -1074,6 +1079,8 @@ github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPn
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY=
github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE=
@@ -1096,6 +1103,7 @@ github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk
github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
@@ -1108,6 +1116,8 @@ github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3d
github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 h1:mZHayPoR0lNmnHyvtYjDeq0zlVHn9K/ZXoy17ylucdo=
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5/go.mod h1:GEXHk5HgEKCvEIIrSpFI3ozzG5xOKA2DVlEX/gGnewM=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
@@ -1151,6 +1161,8 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg=
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -1199,6 +1211,7 @@ golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIi
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1487,6 +1500,8 @@ golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

80
log.go Normal file
View File

@@ -0,0 +1,80 @@
package imageproc
import (
"os"
"time"
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
"github.com/rifflock/lfshook"
"github.com/sirupsen/logrus"
prefixed "github.com/x-cray/logrus-prefixed-formatter"
)
type TagHook struct {
Tag string
}
func NewTagHook(tag string) logrus.Hook {
hook := TagHook{
Tag: tag,
}
return &hook
}
func (hook *TagHook) Fire(entry *logrus.Entry) error {
entry.Data["tag"] = hook.Tag
return nil
}
func (hook *TagHook) Levels() []logrus.Level {
return logrus.AllLevels
}
var stdFormatter *prefixed.TextFormatter // 命令行输出格式
var fileFormatter *prefixed.TextFormatter // 文件输出格式
func init() {
stdFormatter = &prefixed.TextFormatter{
FullTimestamp: true,
TimestampFormat: "2006-01-02.15:04:05",
ForceFormatting: true,
ForceColors: false,
DisableColors: true,
}
fileFormatter = &prefixed.TextFormatter{
FullTimestamp: true,
TimestampFormat: "2006-01-02.15:04:05",
ForceFormatting: true,
ForceColors: false,
DisableColors: true,
}
configureLogger(logrus.StandardLogger(), "log/SJY01-imgproc.log", logrus.InfoLevel)
}
func NewLogger(logfile string) *logrus.Logger {
logger := logrus.New()
configureLogger(logger, logfile, logrus.InfoLevel)
return logger
}
func configureLogger(logger *logrus.Logger, logfile string, level logrus.Level) {
logger.SetFormatter(stdFormatter)
logger.SetLevel(logrus.Level(level))
writer, _ := rotatelogs.New(
logfile+".%Y%m%d",
rotatelogs.WithLinkName(logfile),
rotatelogs.WithMaxAge(time.Duration(30*24)*time.Hour),
rotatelogs.WithRotationTime(time.Duration(24)*time.Hour),
)
lfHook := lfshook.NewHook(lfshook.WriterMap{
logrus.InfoLevel: writer,
logrus.DebugLevel: writer,
logrus.ErrorLevel: writer,
}, fileFormatter)
logger.SetOutput(os.Stdout)
logger.AddHook(lfHook)
}

View File

@@ -139,7 +139,7 @@ func SaveBGRToGDALGTiff(bgr gocv.Mat, bands int, resolution float64, tiffFile st
}
}
log.Info("Saved registered mss to ", tiffFile)
log.Info("Saved BGR MSS to ", tiffFile)
return nil
}

View File

@@ -10,4 +10,5 @@ type Params struct {
PanTiffFile string
MssTiffFile string
FusTIffFile string
SubScenes bool
}

7
run.sh Executable file
View File

@@ -0,0 +1,7 @@
go run cmd/*.go proc -p /Users/lan/workspace/sjy01/preprocessing/demo/output/052022/SJY01_PAN_20240520_115428_052022_103.RAW -m /Users/lan/workspace/sjy01/preprocessing/demo/output/052022/SJY01_MSS_20240520_115428_052022_103.RAW -o data/052022 --fus
go run cmd/*.go proc -p /Users/lan/workspace/sjy01/preprocessing/demo/output/051622/SJY01_PAN_20240516_101236_051622_096.RAW -m /Users/lan/workspace/sjy01/preprocessing/demo/output/051622/SJY01_MSS_20240516_101236_051622_096.RAW -o data/051622 --fus
go run cmd/*.go proc -p /Users/lan/workspace/sjy01/preprocessing/demo/output/051922/SJY01_PAN_20240519_121433_051922_102.RAW -m /Users/lan/workspace/sjy01/preprocessing/demo/output/051922/SJY01_MSS_20240519_121433_051922_102.RAW -o data/051922 --fus
go run cmd/*.go proc -p /Users/lan/workspace/sjy01/preprocessing/demo/output/051814/SJY01_PAN_20240517_111910_051814_098.RAW -m /Users/lan/workspace/sjy01/preprocessing/demo/output/051814/SJY01_MSS_20240517_111910_051814_098.RAW -o data/051814 --fus

163
scenes.go Normal file
View File

@@ -0,0 +1,163 @@
package imageproc
import (
"fmt"
"image"
"os"
"path/filepath"
"strings"
log "github.com/sirupsen/logrus"
"gocv.io/x/gocv"
)
type Scene struct {
Width int
Height int
X int // coordinate of the left top corner of the scene
Y int
Mat []gocv.Mat
Tiff string
}
func (s *Scene) Cleanup() {
for i := range s.Mat {
s.Mat[i].Close()
}
}
// 对 PAN 和 配准后的MSS 在 Y 方向进行分景景之间有25%的重叠
// 默认分景大小:
// MSS 2336 * 2336
// PAN 9344 * 9344
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{
Width: 9344,
Height: y1 - i*hPAN,
X: 0,
Y: i * hPAN,
}
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{
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)
}
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 {
for i, scene := range panScenes {
dir := filepath.Join(r.Params.OutputDir, fmt.Sprintf("%03d", i+1))
os.MkdirAll(dir, 0755)
tiff := filepath.Base(r.Params.PanTiffFile)
tiff = strings.TrimSuffix(tiff, ".tiff")
filename := fmt.Sprintf("%s_%03d.tiff", tiff, i+1)
scene.Tiff = filepath.Join(dir, filename)
err := savePanToGDALGTiff(scene.Mat[0], scene.Tiff)
if err != nil {
log.Errorf("save pan scene %d to tiff failed: %v", i+1, err)
return err
}
}
for i, scene := range mssScenes {
dir := filepath.Join(r.Params.OutputDir, fmt.Sprintf("%03d", i+1))
os.MkdirAll(dir, 0755)
tiff := filepath.Base(r.Params.MssTiffFile)
tiff = strings.TrimSuffix(tiff, ".tiff")
filename := fmt.Sprintf("%s_%03d.tiff", tiff, i+1)
scene.Tiff = filepath.Join(dir, filename)
rgbirImage, _ := r.MergeMSSToBGRNIR(scene.Mat)
err := SaveBGRToGDALGTiff(rgbirImage, 4, 5, scene.Tiff)
if err != nil {
log.Errorf("save mss scene %d to tiff failed: %v", i+1, err)
return err
}
}
return nil
}
func (r *Registrator) DoScenePansharpen(panScenes []*Scene, mssScenes []*Scene) error {
for i := 0; i < len(panScenes); i++ {
// rgbirImg, _ := r.MergeMSSToBGRNIR(mssScenes[i].Mat)
// ihsImage := PansharpenIHS(panScenes[i].Mat[0], rgbirImg)
// path := strings.TrimSuffix(r.Params.MssTiffFile, ".tiff")
// filename := fmt.Sprintf("%s_%03d_FUS.tiff", path, i+1)
// SaveBGRToGDALGTiff(ihsImage, 3, 1.25, filename)
GDALPansharpen(panScenes[i].Tiff, mssScenes[i].Tiff)
}
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")
}
width := channels[0].Cols()
height := channels[0].Rows()
// 创建合并后的图像RGBIR
rgbirImage = gocv.NewMatWithSize(height, width, gocv.MatTypeCV16UC4) // 4通道16位
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
blue := channels[0].GetShortAt(y, x)
green := channels[1].GetShortAt(y, x)
red := channels[2].GetShortAt(y, x)
ir := channels[3].GetShortAt(y, x)
rgbirImage.SetShortAt(y, x*4+0, blue)
rgbirImage.SetShortAt(y, x*4+1, green)
rgbirImage.SetShortAt(y, x*4+2, red)
rgbirImage.SetShortAt(y, x*4+3, ir)
}
}
return rgbirImage, nil
}