parent
b94cc137c7
commit
3b8d55e36f
@ -0,0 +1,336 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include "API_UnderStitch.h"
|
||||
#include "API_FrontStitch.h"
|
||||
#include "PlatformDefine.h"
|
||||
#include <string.h>
|
||||
#include "opencv2/opencv.hpp"
|
||||
#include <random>
|
||||
struct FrameData {
|
||||
int frameNumber;
|
||||
std::string timeRange;
|
||||
int frameCnt;
|
||||
std::string timestamp;
|
||||
float focal_len = 0;
|
||||
float dzoom_ratio = 0;
|
||||
double latitude = 0;
|
||||
double longitude = 0;
|
||||
float rel_alt = 0;
|
||||
float abs_alt = 0;
|
||||
float gb_yaw = 0;
|
||||
float gb_pitch = 0;
|
||||
float gb_roll = 0;
|
||||
|
||||
|
||||
// 衍生参数
|
||||
float real_focal_mm = 0;
|
||||
float pixel_size_um = 0;
|
||||
};
|
||||
|
||||
float extractValueAfter(const std::string& line, const std::string& key) {
|
||||
size_t pos = line.find(key);
|
||||
if (pos == std::string::npos) return 0;
|
||||
|
||||
pos += key.length();
|
||||
size_t end = line.find(' ', pos);
|
||||
if (end == std::string::npos) end = line.length();
|
||||
|
||||
return std::stof(line.substr(pos, end - pos));
|
||||
}
|
||||
|
||||
double extractDoubleAfter(const std::string& line, const std::string& key) {
|
||||
size_t pos = line.find(key);
|
||||
if (pos == std::string::npos) return 0;
|
||||
|
||||
pos += key.length();
|
||||
size_t end = line.find(' ', pos);
|
||||
if (end == std::string::npos) end = line.length();
|
||||
|
||||
return std::stod(line.substr(pos, end - pos));
|
||||
}
|
||||
|
||||
// 获取真实焦距和像元尺寸
|
||||
void inferCameraParams_H20(FrameData& frame, const std::string& filename)
|
||||
{
|
||||
const float full_frame_diag = 43.3f;
|
||||
float sensor_diag = 0.0f;
|
||||
|
||||
if (filename.find("_W") != std::string::npos) {
|
||||
sensor_diag = 9.4f;
|
||||
frame.pixel_size_um = 1.98f;
|
||||
}
|
||||
else if (filename.find("_Z") != std::string::npos) {
|
||||
sensor_diag = 7.7f;
|
||||
frame.pixel_size_um = 2.4f;
|
||||
}
|
||||
else if (filename.find("_T") != std::string::npos) {
|
||||
sensor_diag = 10.9f;
|
||||
frame.pixel_size_um = 12.0f;
|
||||
}
|
||||
else {
|
||||
sensor_diag = 9.4f;
|
||||
frame.pixel_size_um = 1.98f;
|
||||
}
|
||||
|
||||
frame.real_focal_mm = frame.focal_len * (sensor_diag / full_frame_diag);
|
||||
}
|
||||
// 获取真实焦距和像元尺寸
|
||||
void inferCameraParams_H30(FrameData& frame, const std::string& filename)
|
||||
{
|
||||
const float full_frame_diag = 43.3f;
|
||||
float sensor_diag = 0.0f;
|
||||
|
||||
if (filename.find("_W") != std::string::npos) {
|
||||
frame.real_focal_mm = 6.72;
|
||||
frame.pixel_size_um = 2.4;
|
||||
}
|
||||
else if (filename.find("_Z") != std::string::npos) {
|
||||
|
||||
}
|
||||
else if (filename.find("_T") != std::string::npos) {
|
||||
frame.real_focal_mm = 24;
|
||||
frame.pixel_size_um = 12;
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
|
||||
//frame.real_focal_mm = frame.focal_len * (sensor_diag / full_frame_diag);
|
||||
}
|
||||
std::vector<FrameData> parseDJISRT(const std::string& filename) {
|
||||
std::vector<FrameData> frames;
|
||||
std::ifstream file(filename);
|
||||
|
||||
if (!file.is_open()) {
|
||||
std::cerr << "Error: Could not open file " << filename << std::endl;
|
||||
return frames;
|
||||
}
|
||||
|
||||
std::string lines[5];
|
||||
while (std::getline(file, lines[0])) { // Frame number line
|
||||
// Read next 4 lines
|
||||
for (int i = 1; i < 5; ++i) {
|
||||
if (!std::getline(file, lines[i])) break;
|
||||
}
|
||||
|
||||
FrameData frame;
|
||||
|
||||
// Line 1: Frame number
|
||||
frame.frameNumber = std::stoi(lines[0]);
|
||||
|
||||
// Line 2: Time range (00:00:00,000 --> 00:00:00,033)
|
||||
frame.timeRange = lines[1];
|
||||
|
||||
// Line 3: FrameCnt and timestamp
|
||||
std::istringstream iss(lines[2]);
|
||||
std::string temp;
|
||||
iss >> temp >> frame.frameCnt >> frame.timestamp;
|
||||
|
||||
// Line 4: Metadata (direct field extraction)
|
||||
const std::string& meta = lines[3];
|
||||
frame.focal_len = extractValueAfter(meta, "focal_len: ");
|
||||
frame.dzoom_ratio = extractValueAfter(meta, "dzoom_ratio: ");
|
||||
frame.latitude = extractDoubleAfter(meta, "latitude: ");
|
||||
frame.longitude = extractDoubleAfter(meta, "longitude: ");
|
||||
frame.rel_alt = extractValueAfter(meta, "rel_alt: ");
|
||||
frame.abs_alt = extractValueAfter(meta, "abs_alt: ");
|
||||
frame.gb_yaw = extractValueAfter(meta, "gb_yaw: ");
|
||||
frame.gb_pitch = extractValueAfter(meta, "gb_pitch: ");
|
||||
frame.gb_roll = extractValueAfter(meta, "gb_roll: ");
|
||||
|
||||
inferCameraParams_H30(frame, filename);
|
||||
|
||||
frames.push_back(frame);
|
||||
|
||||
// Skip the empty line (line 5)
|
||||
}
|
||||
|
||||
file.close();
|
||||
return frames;
|
||||
}
|
||||
|
||||
|
||||
void ProcDJVideo(vector<std::string> videoPathList, vector<std::string> srtPathList)
|
||||
{
|
||||
auto stitcher = API_UnderStitch::Create();
|
||||
|
||||
stitcher->SetOutput("DJI", "D:/google_tiles");
|
||||
|
||||
|
||||
// dsample
|
||||
int nDownSample = 1;
|
||||
|
||||
GD_VIDEO_FRAME_S frame = { 0 };//输入帧
|
||||
GD_VIDEO_FRAME_S pan = { 0 };//输出全景
|
||||
|
||||
cv::Mat mat_pan;//全景显示
|
||||
|
||||
|
||||
cv::VideoCapture cap(videoPathList[0]);
|
||||
|
||||
// Get video properties
|
||||
double fps = cap.get(cv::CAP_PROP_FPS);
|
||||
int width = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_WIDTH));
|
||||
int height = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_HEIGHT));
|
||||
int frame_count = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_COUNT));
|
||||
|
||||
std::vector<FrameData> srt_init = parseDJISRT(srtPathList[0]);
|
||||
|
||||
FrameInfo info = { 0 };
|
||||
info.nFrmID = 0;
|
||||
info.camInfo.nFocus = srt_init[0].real_focal_mm;
|
||||
info.camInfo.fPixelSize = srt_init[0].pixel_size_um * nDownSample;
|
||||
|
||||
info.craft.stAtt.fYaw = srt_init[0].gb_yaw;
|
||||
info.craft.stAtt.fPitch = srt_init[0].gb_pitch + 90;
|
||||
info.craft.stAtt.fRoll = srt_init[0].gb_roll;
|
||||
|
||||
info.craft.stPos.B = srt_init[0].latitude;
|
||||
info.craft.stPos.L = srt_init[0].longitude;
|
||||
info.craft.stPos.H = srt_init[0].abs_alt;
|
||||
|
||||
|
||||
info.nEvHeight = srt_init[0].abs_alt - srt_init[0].rel_alt;
|
||||
|
||||
info.servoInfo.fServoAz = 0;
|
||||
info.servoInfo.fServoPt = 0;
|
||||
|
||||
info.nWidth = width / nDownSample;
|
||||
info.nHeight = height / nDownSample;
|
||||
|
||||
// 初始化
|
||||
stitcher->Init(info);
|
||||
|
||||
cap.release();
|
||||
|
||||
for (size_t vid = 0; vid < videoPathList.size(); vid++)
|
||||
{
|
||||
printf("Proc %s\n", videoPathList[vid].c_str());
|
||||
cv::VideoCapture cap(videoPathList[vid]);
|
||||
std::vector<FrameData> srt = parseDJISRT(srtPathList[vid]);
|
||||
|
||||
int frmID = 0;
|
||||
while (true)
|
||||
{
|
||||
cv::Mat mat;
|
||||
|
||||
// Read a new frame
|
||||
cap >> mat;
|
||||
|
||||
// Check if frame is empty (end of video)
|
||||
if (mat.empty()) {
|
||||
std::cout << "End of video\n";
|
||||
cap.release();
|
||||
break;
|
||||
}
|
||||
|
||||
frmID++;
|
||||
Mat mat_ds2;
|
||||
|
||||
cv::resize(mat, mat_ds2, cv::Size(width / nDownSample, height / nDownSample));
|
||||
|
||||
|
||||
|
||||
FrameInfo info = { 0 };
|
||||
info.nFrmID = frmID;
|
||||
info.camInfo.nFocus = srt[frmID].real_focal_mm;
|
||||
info.camInfo.fPixelSize = srt[frmID].pixel_size_um * nDownSample;
|
||||
|
||||
info.craft.stAtt.fYaw = srt[frmID].gb_yaw;
|
||||
info.craft.stAtt.fPitch = srt[frmID].gb_pitch + 90;
|
||||
info.craft.stAtt.fRoll = srt[frmID].gb_roll;
|
||||
|
||||
info.craft.stPos.B = srt[frmID].latitude;
|
||||
info.craft.stPos.L = srt[frmID].longitude;
|
||||
info.craft.stPos.H = srt[frmID].abs_alt;
|
||||
|
||||
|
||||
info.nEvHeight = srt[frmID].abs_alt;
|
||||
|
||||
info.servoInfo.fServoAz = 0;
|
||||
info.servoInfo.fServoPt = 0;
|
||||
|
||||
info.nWidth = mat_ds2.cols;
|
||||
info.nHeight = mat_ds2.rows;
|
||||
|
||||
|
||||
frame.enPixelFormat = GD_PIXEL_FORMAT_RGB_PACKED;
|
||||
frame.u32Width = mat_ds2.cols;
|
||||
frame.u32Height = mat_ds2.rows;
|
||||
frame.u64VirAddr[0] = mat_ds2.data;
|
||||
|
||||
if (frmID % 100 != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
std::cout << info.craft.stPos.B << " " << info.craft.stPos.L << " " << info.craft.stPos.H << " "
|
||||
<< info.craft.stAtt.fYaw << " " << info.craft.stAtt.fPitch << " " << info.craft.stAtt.fRoll << " "
|
||||
<< info.servoInfo.fServoAz << " " << info.servoInfo.fServoPt
|
||||
<< std::endl;
|
||||
|
||||
cv::TickMeter tm;
|
||||
tm.start();
|
||||
// 基于外参的快拼
|
||||
stitcher->Run(frame, info);
|
||||
|
||||
tm.stop();
|
||||
|
||||
mat_pan = stitcher->ExportPanMat();
|
||||
Mat pan_rgb, pan_rgb_ds;
|
||||
cv::cvtColor(mat_pan, pan_rgb, cv::COLOR_BGRA2BGR);
|
||||
|
||||
cv::resize(pan_rgb, pan_rgb_ds, cv::Size(pan_rgb.cols / 8, pan_rgb.rows / 8));
|
||||
|
||||
imshow("pan_rgb", pan_rgb_ds);
|
||||
cv::waitKey(1);
|
||||
|
||||
}
|
||||
|
||||
cv::TickMeter tm;
|
||||
tm.start();
|
||||
// 处理帧
|
||||
stitcher->OptAndOutCurrPan();
|
||||
|
||||
tm.stop();
|
||||
|
||||
std::cout << "time opt:" << tm.getTimeMilli() << std::endl;
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
using std::string;
|
||||
|
||||
int main()
|
||||
{
|
||||
vector<std::string> videoPathList;
|
||||
vector<std::string> srtPathList;
|
||||
|
||||
string folder = "F:/DJI_202504181507_016/";
|
||||
|
||||
//
|
||||
videoPathList.push_back(folder + "DJI_20250418152649_0005_W.MP4");
|
||||
srtPathList.push_back(folder + "DJI_20250418152649_0005_W.srt");
|
||||
|
||||
//videoPathList.push_back(folder + "DJI_20250418153043_0006_T.MP4");
|
||||
//srtPathList.push_back(folder + "DJI_20250418153043_0006_T.srt");
|
||||
|
||||
//videoPathList.push_back(folder + "DJI_20250418152649_0005_T.MP4");
|
||||
//srtPathList.push_back(folder + "DJI_20250418152649_0005_T.srt");
|
||||
|
||||
|
||||
|
||||
ProcDJVideo(videoPathList, srtPathList);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Binary file not shown.
@ -0,0 +1,9 @@
|
||||
import ffmpeg
|
||||
|
||||
input_file = "I:/DJI_20250418144441_0002_W.MP4"
|
||||
output_file = "I:/DJI_20250418144441_0002_W.srt"
|
||||
|
||||
ffmpeg.input(input_file).output(output_file).run()
|
||||
|
||||
|
||||
|
Loading…
Reference in new issue