aux extraction

This commit is contained in:
nuknal
2024-05-15 12:50:52 +08:00
parent 3cd797cd4a
commit 6f76b2f131
10 changed files with 561 additions and 181 deletions

247
aux.go Normal file
View File

@@ -0,0 +1,247 @@
package main
import (
"bufio"
"encoding/binary"
"errors"
"os"
"path/filepath"
"strings"
"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
}
// 中心机辅助数据 512 字节
type AuxCenterMachine struct {
}
// 焦面电箱辅助数据 128 字节
type AuxFocalBox struct {
}
// 从传输帧文件中分离辅助数据,分别存储到辅助数据文件 _AUX.dat 和图像数据文件 _IMG_{波谱}.dat 中
func (p *Processor) 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)
name := filepath.Base(sDataFile)
name = strings.TrimRight(name, filepath.Ext(name))
aux0 := filepath.Dir(sDataFile) + "/" + name + "_AUX0.dat"
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 := filepath.Dir(sDataFile) + "/" + name + "_AUX1.dat"
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 := filepath.Dir(sDataFile) + "/" + 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(filepath.Dir(sDataFile)+"/"+name+"_IMG_PAN.HDR", &panEnviHdr)
defer wpanHdr.Close()
// 先按单波段存储,再按波段组合存储为 BSQ 格式的 MSS
mss := filepath.Dir(sDataFile) + "/" + 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(filepath.Dir(sDataFile)+"/"+name+"_IMG_MSS.HDR", &mssEnviHdr)
defer wmssHdr.Close()
var afh AuxFrameHead
dataLen := len(sData)
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++
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")
break
}
// 目前只支持线阵模式
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.Info("length of row data is not enough for row length:", 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])
dataIndex += 1192
mssEnviHdr.Lines += 1
}
if afh.B2 {
wmss.Write(sData[dataIndex : dataIndex+1192])
dataIndex += 1192
}
if afh.B3 {
wmss.Write(sData[dataIndex : dataIndex+1192])
dataIndex += 1192
}
if afh.B4 {
wmss.Write(sData[dataIndex : dataIndex+1192])
dataIndex += 1192
}
i = dataIndex // 完成一行数据解析
}
panEnviHdr.Samples = 9520
panEnviHdr.Bands = 1
wpanHdr.Write([]byte(panEnviHdr.String()))
mssEnviHdr.Lines = mssEnviHdr.Lines / 4 // 多光谱波段分别在 4 行中传输
mssEnviHdr.Bands = 1
mssEnviHdr.Samples = 2384 * 4
wmssHdr.Write([]byte(mssEnviHdr.String()))
return nil
}