141 lines
3.6 KiB
Go
141 lines
3.6 KiB
Go
package rrc
|
||
|
||
import (
|
||
"os"
|
||
|
||
log "github.com/sirupsen/logrus"
|
||
"gocv.io/x/gocv"
|
||
)
|
||
|
||
// Relative Radiation Correction
|
||
// 采用在轨统计定标方法。利用卫星在轨后获取的常规影像数据,统计每个探元出现的灰度频次。
|
||
|
||
const (
|
||
PANCameraProbeNum = 9344 // 全色探元数
|
||
MSSCameraProbeNum = 2336 // 多光谱探元数
|
||
MaxGrayLevel = 65536
|
||
)
|
||
|
||
type RRC struct {
|
||
PANDataSet []string
|
||
MSSDataSet []string
|
||
|
||
Histograms [5]BandHistogram
|
||
}
|
||
|
||
type BandHistogram struct {
|
||
width int // 探元数
|
||
N_i []int // N_i 探元像素总数 PAN 0-9343 MSS 0-2335
|
||
n_ik [][]int // n_ik 第i探元灰度等级为k的像素数统计 PAN 9343 x 65536 MSS 2335 x 65536
|
||
p_ik [][]float64 // p_ik = n_ik / N_i 探元灰度概率密度 PAN 9343 x 65536 MSS 2335 x 65536
|
||
m_l []int64 // 具有灰度等级l的像素总数 l = 0-65535
|
||
M int64 // 参与直方图统计的总像素数
|
||
P_l []float64 // P_l = m_l/M 所有探元的期望直方图灰度等级为l的概率密度
|
||
S_ik [][]float64 // S_ik = sum(p_ij),j=0..k 第i个探元直方图灰度等级k的累积概率密度
|
||
V_l []float64 // V_l = sum(P_j),j=0..l // 期望直方图灰度级l对应的累积概率密度
|
||
Tij [][]float64 // 第i个像元的j灰度等级对应的新的灰度值,用于修正图像
|
||
}
|
||
|
||
func (hist *BandHistogram) init(width int) {
|
||
hist.width = width
|
||
hist.M = 0
|
||
hist.N_i = make([]int, width)
|
||
hist.n_ik = make([][]int, width)
|
||
hist.p_ik = make([][]float64, width)
|
||
hist.m_l = make([]int64, MaxGrayLevel)
|
||
hist.P_l = make([]float64, MaxGrayLevel)
|
||
hist.S_ik = make([][]float64, width)
|
||
hist.V_l = make([]float64, MaxGrayLevel)
|
||
hist.Tij = make([][]float64, width)
|
||
|
||
for i := 0; i < width; i++ {
|
||
hist.n_ik[i] = make([]int, MaxGrayLevel)
|
||
hist.p_ik[i] = make([]float64, MaxGrayLevel)
|
||
hist.S_ik[i] = make([]float64, MaxGrayLevel)
|
||
hist.Tij[i] = make([]float64, MaxGrayLevel)
|
||
}
|
||
}
|
||
|
||
// 统计探元灰度的累积概率密度
|
||
func (rrc *RRC) StatisticalPAN(l0 string) error {
|
||
data, err := os.ReadFile(l0)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
height := len(data) / (PANCameraProbeNum * 2)
|
||
img, err := gocv.NewMatFromBytes(height, PANCameraProbeNum, gocv.MatTypeCV16U, data)
|
||
if err != nil {
|
||
log.Error("Error creating Mat from bytes: ", err)
|
||
return err
|
||
}
|
||
|
||
hist := BandHistogram{}
|
||
hist.init(PANCameraProbeNum)
|
||
|
||
rrc.statistical(img, &hist)
|
||
rrc.compute(&hist)
|
||
rrc.output(&hist, "pan_gray_table.tif")
|
||
|
||
return nil
|
||
}
|
||
|
||
func (rrc *RRC) statistical(img gocv.Mat, hist *BandHistogram) error {
|
||
hist.M += int64(img.Rows() * img.Cols())
|
||
|
||
for i := 0; i < hist.width; i++ {
|
||
hist.N_i[i] += img.Rows()
|
||
}
|
||
|
||
for y := 0; y < img.Rows(); y++ {
|
||
for x := 0; x < img.Cols(); x++ {
|
||
gray := uint16(img.GetShortAt(x, y))
|
||
hist.n_ik[x][gray]++
|
||
}
|
||
}
|
||
|
||
for gray := 0; gray < MaxGrayLevel; gray++ {
|
||
for i := 0; i < hist.width; i++ {
|
||
hist.m_l[gray] += int64(hist.n_ik[i][gray])
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
func (rrc *RRC) compute(hist *BandHistogram) error {
|
||
width := len(hist.N_i)
|
||
|
||
for i := 0; i < width; i++ {
|
||
for k := 0; k < MaxGrayLevel; k++ {
|
||
hist.p_ik[i][k] = float64(hist.n_ik[i][k]) / float64(hist.N_i[i])
|
||
}
|
||
}
|
||
|
||
for gray := 0; gray < MaxGrayLevel; gray++ {
|
||
hist.P_l[gray] = float64(hist.m_l[gray]) / float64(hist.M)
|
||
}
|
||
|
||
for i := 0; i < width; i++ {
|
||
for k := 0; k < MaxGrayLevel; k++ {
|
||
hist.S_ik[i][k] = 0
|
||
for j := 0; j <= k; j++ {
|
||
hist.S_ik[i][k] += hist.p_ik[i][j]
|
||
}
|
||
}
|
||
}
|
||
|
||
for gray := 0; gray < MaxGrayLevel; gray++ {
|
||
hist.V_l[gray] = 0
|
||
for j := 0; j <= gray; j++ {
|
||
hist.V_l[gray] += hist.P_l[j]
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
func (rrc *RRC) output(hist *BandHistogram, referenceTIF string) error {
|
||
return nil
|
||
}
|