Files
sjy01-preprocessing/extract/aux.go
2024-05-16 17:33:33 +08:00

326 lines
8.6 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 extract
import (
"bufio"
"encoding/binary"
"errors"
"fmt"
"os"
"path/filepath"
"sort"
"strings"
"time"
"github.com/sirupsen/logrus"
log "github.com/sirupsen/logrus"
)
// 每行传感器数据帧头信息长度为24字节
type AuxFrameHead struct {
PkgHead [4]byte // 包头头标识符固定为0xD15BD15B
FillByte0 byte // 填充字节 0x00
FrmHead [6]byte // 帧头标识符固定为0xEB90EB90EB90
// 图像模式
// B7 模式标识 000为线阵模式
// B6
// B5
// B4 B4谱状态 0不输出1输出
// B3 B3谱状态 0不输出1输出
// B2 B2谱状态 0不输出1输出
// B1 B1谱状态 0不输出1输出
// B0 全色状态 0不输出1输出
ImgMode byte
SerialNo uint32 // 当前流水号
TimeSec uint32 // 时间(秒) 量纲1us/bit十六进制无符号整型数
TimeSecFrac uint32 // 秒小数
FileNo uint8 // 文件号
IsValidFrmHead bool
B0 bool
B1 bool
B2 bool
B3 bool
B4 bool
IsLinerMatrix bool
RowLength int
}
func (afh *AuxFrameHead) Decode(data []byte) error {
if len(data) < 24 {
return errors.New("length of AuxFrameHead is not 24")
}
afh.PkgHead = [4]byte{data[0], data[1], data[2], data[3]}
afh.FillByte0 = data[4]
afh.FrmHead = [6]byte{data[5], data[6], data[7], data[8], data[9], data[10]}
afh.ImgMode = data[11]
afh.B0 = (afh.ImgMode&(1<<0) != 0x0)
afh.B1 = (afh.ImgMode&(1<<1) != 0x0)
afh.B2 = (afh.ImgMode&(1<<2) != 0x0)
afh.B3 = (afh.ImgMode&(1<<3) != 0x0)
afh.B4 = (afh.ImgMode&(1<<4) != 0x0)
afh.IsLinerMatrix = (afh.ImgMode&(1<<5) == 0x0 && afh.ImgMode&(1<<6) == 0x0 && afh.ImgMode&(1<<7) == 0x0)
afh.SerialNo = binary.BigEndian.Uint32(data[12:16])
afh.TimeSec = binary.BigEndian.Uint32(data[16:20])
afh.TimeSecFrac = uint32(uint32(data[20])<<16 | uint32(data[21])<<8 | uint32(data[22])) //binary.BigEndian.Uint32(data[20:23])
afh.FileNo = data[23]
afh.RowLength = afh.LengthOfRow()
afh.IsValidFrmHead = afh.CheckFrmHead()
return nil
}
// 计算一行数据长度:帧头+辅助数据+图像数据
func (afh AuxFrameHead) LengthOfRow() int {
if !afh.IsLinerMatrix {
return 14344
}
length := 64 // 帧头+辅助数据长度
if afh.B0 {
length += 19040
}
if afh.B1 {
length += 1192
}
if afh.B2 {
length += 1192
}
if afh.B3 {
length += 1192
}
if afh.B4 {
length += 1192
}
return length
}
func (afh AuxFrameHead) CheckFrmHead() bool {
if afh.FrmHead[0] == 0xEB && afh.FrmHead[1] == 0x90 &&
afh.FrmHead[2] == 0xEB && afh.FrmHead[3] == 0x90 &&
afh.FrmHead[4] == 0xEB && afh.FrmHead[5] == 0x90 {
return true
}
return false
}
type Record struct {
index int
frmHead *AuxFrameHead
}
// 从传输帧文件中分离辅助数据,分别存储到辅助数据文件 _AUX.dat 和图像数据文件 _IMG_{波谱}.dat 中
func (p *Extractor) SeprateAuxAndImgData(sDataFile string) error {
// 打开传输帧文件 - 一次读入内存
sData, err := os.ReadFile(sDataFile)
if err != nil {
log.Println("read data from", sDataFile, "error:", err.Error())
return err
}
log.Info("seprate aux and img data from", sDataFile)
// 数据质量分析
fimg, _ := os.Create("demo/temp/" + p.params.DataId + "_aux_img.txt")
defer fimg.Close()
fimg.WriteString("字节数 帧头流水号 文件号 帧头时间 中心辅助数据前4字节(行33-36)\n")
var qmap []*Record
for i := 0; i < len(sData); {
// 解析帧
if i+24 > len(sData) {
log.Info("length of original image frame head is not engough: ", len(sData)-i)
break
}
if sData[i] == 0xD1 && sData[i+1] == 0x5B && sData[i+2] == 0xD1 && sData[i+3] == 0x5B {
log.Debug("find package head: 0xD15BD15B")
} else {
i++
// log.Println(i,"not find package head: 0xD15BD15B, skip 1 byte")
continue
}
afh := &AuxFrameHead{}
afh.Decode(sData[i : i+24])
if !afh.IsValidFrmHead {
log.Debugf("[%d] invalid frame head of original raw data %v", i, afh.FrmHead)
i += 1
} else {
r := &Record{index: i, frmHead: afh}
qmap = append(qmap, r)
i += 24
utcTime := binary.BigEndian.Uint32(sData[i+32 : i+36])
t := time.Unix(int64(afh.TimeSec+uint32(ReferenceTime2000)), 0)
tAux := time.Unix(int64(utcTime), 0)
startAuxLine := tAux.Year() == t.Year() && tAux.Month() == t.Month() && tAux.Day() == t.Day() &&
tAux.Hour() == t.Hour() && tAux.Minute() == t.Minute()
if startAuxLine {
fimg.WriteString("----- AUX Start -----\n")
}
fimg.WriteString(fmt.Sprintf("%d %d %d %s %s\n",
i,
afh.SerialNo,
afh.FileNo,
t.String(),
tAux.String(),
))
}
}
sort.Slice(qmap, func(i, j int) bool {
return qmap[i].index < qmap[j].index
})
name := filepath.Base(sDataFile)
name = strings.TrimRight(name, filepath.Ext(name))
outputDir := p.params.OutputPath
aux0 := outputDir + "/" + name + "_EB.AUX"
os.Remove(aux0)
faux0, _ := os.OpenFile(aux0, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777)
waux0 := bufio.NewWriter(faux0)
defer waux0.Flush()
defer faux0.Close()
aux1 := outputDir + "/" + name + "_PLAT.AUX"
os.Remove(aux1)
faux1, _ := os.OpenFile(aux1, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777)
waux1 := bufio.NewWriter(faux1)
defer waux1.Flush()
defer faux1.Close()
pan := outputDir + "/" + name + "_IMG_PAN.RAW"
os.Remove(pan)
fpan, _ := os.OpenFile(pan, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777)
wpan := bufio.NewWriter(fpan)
defer wpan.Flush()
defer fpan.Close()
panEnviHdr := EnviHdr{}
wpanHdr, _ := NewBSQWriter(outputDir+"/"+name+"_IMG_PAN.HDR", &panEnviHdr)
defer wpanHdr.Close()
// 先按单波段存储,再按波段组合存储为 BSQ 格式的 MSS
mss := outputDir + "/" + name + "_IMG_MSS.RAW"
os.Remove(mss)
fmss, _ := os.OpenFile(mss, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777)
wmss := bufio.NewWriter(fmss)
defer wmss.Flush()
defer fmss.Close()
mssEnviHdr := EnviHdr{}
wmssHdr, _ := NewBSQWriter(outputDir+"/"+name+"_IMG_MSS.HDR", &mssEnviHdr)
defer wmssHdr.Close()
var afh AuxFrameHead
dataLen := len(sData)
mssData := make([][]byte, 4)
for i := 0; i < dataLen; {
if i+4 > dataLen {
logrus.Println("end of data, dataLen:", dataLen, "i:", i)
break
}
// 包头
if sData[i] == 0xD1 && sData[i+1] == 0x5B && sData[i+2] == 0xD1 && sData[i+3] == 0x5B {
log.Debug("find package head: 0xD15BD15B")
} else {
i++
// log.Println("not find package head: 0xD15BD15B, skip 1 byte")
continue
}
// 解析帧
if i+24 > dataLen {
log.Info("length of frame head is not engough for frame head")
break
}
afh.Decode(sData[i : i+24])
// pp.Println(afh)
if !afh.IsValidFrmHead {
log.Info("invalid frame head of original raw data")
i += 1
continue
}
// 目前只支持线阵模式
if !afh.IsLinerMatrix {
log.Error("not liner matrix mode, only support liner matrix mode")
break
}
// 读取一行数据 sData[i : i+afh.RowLength]
if i+afh.RowLength > dataLen {
log.Infof("length of image row data %v is not enough: %v", dataLen-i, afh.RowLength)
break
}
// 存储辅助数据到临时文件
dataIndex := i + 24
waux0.Write(sData[dataIndex : dataIndex+8]) // 8字节焦面电箱辅助数据
dataIndex += 8
waux1.Write(sData[dataIndex : dataIndex+32]) // 32字节中心机辅助数据
dataIndex += 32
// 存储图像数据到临时文件 - 以 ENVI BSQ 格式存储,同时提供 HDR 描述文件
if afh.B0 {
wpan.Write(sData[dataIndex : dataIndex+19040])
dataIndex += 19040
panEnviHdr.Lines += 1
}
if afh.B1 {
// wmss.Write(sData[dataIndex : dataIndex+1192])
mssData[0] = append(mssData[0], sData[dataIndex:dataIndex+1192]...)
dataIndex += 1192
mssEnviHdr.Lines += 1
}
if afh.B2 {
// wmss.Write(sData[dataIndex : dataIndex+1192])
mssData[1] = append(mssData[1], sData[dataIndex:dataIndex+1192]...)
dataIndex += 1192
}
if afh.B3 {
// wmss.Write(sData[dataIndex : dataIndex+1192])
mssData[2] = append(mssData[2], sData[dataIndex:dataIndex+1192]...)
dataIndex += 1192
}
if afh.B4 {
// wmss.Write(sData[dataIndex : dataIndex+1192])
mssData[3] = append(mssData[3], sData[dataIndex:dataIndex+1192]...)
dataIndex += 1192
}
i = dataIndex // 完成一行数据解析
}
var bands = 0
for i := 0; i < 4; i++ {
if len(mssData[i]) > 0 {
log.Println("write mss data of band B", i+1)
_, err := wmss.Write(mssData[i])
if err != nil {
log.Error("write mss data error:", err.Error())
}
bands += 1
}
}
panEnviHdr.Samples = 9520
panEnviHdr.Bands = 1
wpanHdr.Write([]byte(panEnviHdr.String()))
mssEnviHdr.Lines = mssEnviHdr.Lines / 4 // 多光谱波段分别在 4 行中传输
mssEnviHdr.Samples = 2384
mssEnviHdr.Bands = bands
wmssHdr.Write([]byte(mssEnviHdr.String()))
return nil
}