algoLib/HessianTable/HessianTable.cpp
2025-08-18 14:40:59 +08:00

818 lines
27 KiB
C++
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.

// HessianTable.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <vector>
#include <cmath>
#include <corecrt_math_defines.h>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cstring>
//#include <stdio.h>
//#include <stdint.h>
using namespace std;
#if 0
// 生成1D无偏高斯二阶导数掩模
vector<double> generate_1d_mask(double sigma, int radius) {
int size = 2 * radius + 1;
vector<double> mask(size, 0.0);
double sigma_sq = sigma * sigma;
double normalization = 1.0 / (sqrt(2 * M_PI) * sigma_sq * sigma);
for (int i = -radius; i <= radius; ++i) {
double x_low = i - 0.5;
double x_high = i + 0.5;
// 计算高斯二阶导数在区间[x_low, x_high]的积分
double term1 = x_low * exp(-x_low * x_low / (2 * sigma_sq));
double term2 = x_high * exp(-x_high * x_high / (2 * sigma_sq));
double integral = (term1 - term2) / sigma_sq;
// 积分第二部分:误差函数处理常数项
double erf_term = erf(x_high / (sigma * sqrt(2))) - erf(x_low / (sigma * sqrt(2)));
integral += erf_term * sigma * sqrt(M_PI / 2);
integral *= normalization;
mask[i + radius] = integral;
}
return mask;
}
// 1D卷积函数处理边界为0扩展
vector<double> convolve_1d(const vector<double>& signal, const vector<double>& mask) {
int mask_size = mask.size();
int radius = (mask_size - 1) / 2;
vector<double> result(signal.size(), 0.0);
for (int i = 0; i < signal.size(); ++i) {
double sum = 0.0;
for (int j = -radius; j <= radius; ++j) {
int pos = i + j;
if (pos >= 0 && pos < signal.size()) {
sum += signal[pos] * mask[j + radius];
}
}
result[i] = sum;
}
return result;
}
int main() {
// 示例参数
double sigma = 2.0;
int radius = static_cast<int>(ceil(3 * sigma));
// 生成掩模
vector<double> mask = generate_1d_mask(sigma, radius);
// 输出掩模系数
cout << "Convolution Mask Coefficients:\n";
for (double coeff : mask) {
cout << coeff << " ";
}
cout << endl;
// 示例信号(可根据需要修改)
vector<double> signal = { 0, 0, 0, 1, 1, 1, 0, 0, 0 };
// 应用卷积
vector<double> response = convolve_1d(signal, mask);
// 输出响应
cout << "Convolution Response:\n";
for (double val : response) {
cout << val << " ";
}
cout << endl;
return 0;
}
#include <vector>
#include <cmath>
#include <iostream>
using namespace std;
// 生成1D无偏高斯一阶导数掩模
vector<double> generate_1d_first_derivative_mask(double sigma, int radius) {
int size = 2 * radius + 1;
vector<double> mask(size, 0.0);
double sigma_sq = sigma * sigma;
double normalization = 1.0 / (sigma * sqrt(2 * M_PI)); // 高斯函数归一化因子
for (int i = -radius; i <= radius; ++i) {
double x_low = i - 0.5;
double x_high = i + 0.5;
// 计算高斯函数在离散区间端点的值
double g_low = exp(-x_low * x_low / (2 * sigma_sq)) * normalization;
double g_high = exp(-x_high * x_high / (2 * sigma_sq)) * normalization;
// 积分结果 = G(x_low) - G(x_high)
double integral = g_low - g_high;
mask[i + radius] = integral;
}
return mask;
}
// 卷积函数(与之前的二阶实现相同)
vector<double> convolve_1d(const vector<double>& signal, const vector<double>& mask) {
int mask_size = mask.size();
int radius = (mask_size - 1) / 2;
vector<double> result(signal.size(), 0.0);
for (int i = 0; i < signal.size(); ++i) {
double sum = 0.0;
for (int j = -radius; j <= radius; ++j) {
int pos = i + j;
if (pos >= 0 && pos < signal.size()) {
sum += signal[pos] * mask[j + radius];
}
}
result[i] = sum;
}
return result;
}
int main() {
// 示例参数
double sigma = 2.0;
int radius = static_cast<int>(ceil(3 * sigma));
// 生成一阶导数掩模
vector<double> mask_1st = generate_1d_first_derivative_mask(sigma, radius);
// 输出掩模系数
cout << "1st Derivative Mask Coefficients:\n";
for (double coeff : mask_1st) {
cout << coeff << " ";
}
cout << endl;
// 示例信号(阶跃边缘)
vector<double> signal = { 0, 0, 0, 0, 1, 1, 1, 1, 1 };
// 计算一阶导数响应
vector<double> response = convolve_1d(signal, mask_1st);
// 输出响应
cout << "1st Derivative Response:\n";
for (double val : response) {
cout << val << " ";
}
cout << endl;
return 0;
}
#endif
#define LUMA_RGN_DATA_WIN_SIZE 16
#define LUMA_GEN_DATA_SCALE 100
typedef struct
{
unsigned short WinRdx;//窗口在图像内的起始坐标
unsigned short y; //y坐标
unsigned short Rid; //region的ID
unsigned char Flag; //bit0是overlap标志。bit1是反光信号标志
unsigned char PeakRltvRdx; //peak在窗口内的的相对坐标低4位是起始坐标高4位是结束坐标
unsigned char data[LUMA_RGN_DATA_WIN_SIZE];
double offset;
}Luma_rgnData;
typedef struct
{
double true_offset;
double compute_offset;
double nCom_offset;
}Luma_offsetTestCompare;
//生成测试数据:
//sigma:(1.0,2.0,3.0,4.0,5.0),
//Peak:204060100200250
//Offset: (-0.5,-0.4,-0.3,-0.2,-0.1,0,0.1,0.2,0.3,0.4)
//每次调用生成Offset遍历数据(-0.5,-0.4,-0.3,-0.2,-0.1,0,0.1,0.2,0.3,0.4)
std::vector<Luma_rgnData> _genTestData(double sigma, double peakValue)
{
//int size = 10;
//double offsetTable[10] = {-0.5,-0.4,-0.3,-0.2,-0.1,0,0.1,0.2,0.3,0.4};
int size = 20;
double offsetTable[20] = { -0.5,-0.45,-0.4,-0.35, -0.3,-0.25, -0.2,-0.15, -0.1, -0.05,
0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45 };
std::vector< Luma_rgnData> result;
int buffSize = (LUMA_RGN_DATA_WIN_SIZE + 3) * LUMA_GEN_DATA_SCALE;
std::vector<double> dataBuffer(buffSize, 0);
int radius = (LUMA_RGN_DATA_WIN_SIZE + 3)/2;
int id = 0;
double sigma2 = sigma * sigma;
for (int i = -radius; i <= radius; i++)
{
for (int j = 0; j < LUMA_GEN_DATA_SCALE; j++)
{
double x = (double)i + (double)j / LUMA_GEN_DATA_SCALE;
dataBuffer[id] = exp(-x * x / (2 * sigma2));
id++;
}
}
//生成结果数据
int dataWin = LUMA_RGN_DATA_WIN_SIZE / 2;
int y = 0;
for (int n = 0; n < size; n++) //取不同的offset进行计算
{
double offset = offsetTable[n];
int offsetPos = (int)(-offset * LUMA_GEN_DATA_SCALE) - LUMA_GEN_DATA_SCALE/2; //位于中心
double rsltData[LUMA_RGN_DATA_WIN_SIZE];
for (int i = 0; i < LUMA_RGN_DATA_WIN_SIZE; i++)//第个测试样本有16个数据高斯分布偏离位置为offset
{
double sum = 0;
int pos = offsetPos + (i-dataWin) * LUMA_GEN_DATA_SCALE + radius * LUMA_GEN_DATA_SCALE;
for (int j = 0; j < LUMA_GEN_DATA_SCALE; j++) //过采样间隔为0.01
sum += dataBuffer[j + pos];
rsltData[i] = sum;
}
double maxData = 0;
for (int i = 0; i < LUMA_RGN_DATA_WIN_SIZE; i++)
{
if (maxData < rsltData[i])
maxData = rsltData[i];
}
Luma_rgnData a_sample;
memset(&a_sample, 0, sizeof(Luma_rgnData));
a_sample.y = y;
y++;
a_sample.Rid = 1;
a_sample.PeakRltvRdx = 0xC3;
a_sample.offset = offset;
for (int i = 0; i < LUMA_RGN_DATA_WIN_SIZE; i++)
{
double d = (rsltData[i] / maxData) * peakValue;
if (d > 254.0)
a_sample.data[i] = 254.0;
else
a_sample.data[i] = (unsigned char)d;
}
result.push_back(a_sample);
}
return result;
}
//直接采样法
// 高斯一阶导数掩模生成
vector<double> generate_1st_mask_directSample(double sigma, int radius) {
int size = 2 * radius + 1;
vector<double> mask(size, 0.0);
double sigma2 = sigma * sigma;
double norm = 1.0 / (sigma * sigma2 * sqrt(2 * M_PI));
for (int i = -radius; i <= radius; ++i) {
double x = i;
mask[i + radius] = -x * exp(-x * x / (2 * sigma2));
mask[i + radius] *= norm;
}
return mask;
}
// 高斯二阶导数掩模生成
vector<double> generate_2nd_mask_directSample(double sigma, int radius) {
int size = 2 * radius + 1;
vector<double> mask(size, 0.0);
double sigma2 = sigma * sigma;
double sigma4 = sigma2 * sigma2;
double norm = 1.0 / (sqrt(2 * M_PI) * sigma * sigma4);
for (int i = -radius; i <= radius; ++i) {
double x = i;
mask[i + radius] = (x * x - sigma2) * exp(-x * x / (2 * sigma2));
mask[i + radius] *= norm;
}
return mask;
}
//积分法
// 高斯一阶导数掩模生成
vector<double> generate_1st_mask_Integral(double sigma, int radius) {
int size = 2 * radius + 1;
vector<double> mask(size, 0.0);
double norm = 1.0 / (sigma * sqrt(2 * M_PI));
for (int i = -radius; i <= radius; ++i) {
double x_low = i - 0.5;
double x_high = i + 0.5;
mask[i + radius] = exp(-x_high * x_high / (2 * sigma * sigma)) -
exp(-x_low * x_low / (2 * sigma * sigma));
mask[i + radius] *= norm;
}
return mask;
}
// 高斯二阶导数掩模生成
vector<double> generate_2nd_mask_Integral(double sigma, int radius) {
int size = 2 * radius + 1;
vector<double> mask(size, 0.0);
double sigma2 = sigma * sigma;
double norm = 1.0 / (sqrt(2 * M_PI) * sigma * sigma2);
for (int i = -radius; i <= radius; ++i) {
double x_low = i - 0.5;
double x_high = i + 0.5;
double term1 = x_low * exp(-x_low * x_low / (2 * sigma2));
double term2 = x_high * exp(-x_high * x_high / (2 * sigma2));
mask[i + radius] = term1 - term2;
mask[i + radius] *= norm;
}
return mask;
}
// 卷积函数
vector<double> convolve(const vector<double>& signal, const vector<double>& mask) {
int radius = (mask.size() - 1) / 2;
vector<double> result(signal.size(), 0.0);
for (int i = 0; i < signal.size(); ++i) {
double sum = 0.0;
for (int j = -radius; j <= radius; ++j) {
int pos = i + j;
if (pos >= 0 && pos < signal.size()) {
sum += signal[pos] * mask[j + radius];
}
}
result[i] = sum;
}
return result;
}
void _genSubpixMask(
double sigma,
int radius,
std::vector<double>& outMask_1st,
std::vector<double>& outMask_2nd)
{
// 生成掩模
auto mask_1st = generate_1st_mask_directSample(sigma, radius);
auto mask_2nd = generate_2nd_mask_directSample(sigma, radius);
auto mask_1st_integ = generate_1st_mask_Integral(sigma, radius);
auto mask_2nd_integ = generate_2nd_mask_Integral(sigma, radius);
//生成宽度为LUMA_RGN_DATA_WIN_SIZE的mask
std::vector<double> objMask_1st(LUMA_RGN_DATA_WIN_SIZE, 0.0);
int size_1st = mask_1st_integ.size();
for (int i = 0; i < LUMA_RGN_DATA_WIN_SIZE; i++)
{
int pos = size_1st / 2 - LUMA_RGN_DATA_WIN_SIZE / 2 + i;
if ((pos < 0) || (pos >= size_1st))
objMask_1st[i] = 0;
else
objMask_1st[i] = mask_1st_integ[pos];
}
objMask_1st[0] = 0;
for (int i = 0, i_max = objMask_1st.size(); i < i_max; i++)
outMask_1st.push_back(objMask_1st[i]);
std::vector<double> objMask_2nd(LUMA_RGN_DATA_WIN_SIZE, 0.0);
int size_2nd = mask_2nd_integ.size();
for (int i = 0; i < LUMA_RGN_DATA_WIN_SIZE; i++)
{
int pos = size_2nd / 2 - LUMA_RGN_DATA_WIN_SIZE / 2 + i;
if ((pos < 0) || (pos >= size_2nd))
objMask_2nd[i] = 0;
else
objMask_2nd[i] = mask_2nd_integ[pos];
}
objMask_2nd[0] = 0;
for (int i = 0, i_max = objMask_2nd.size(); i < i_max; i++)
outMask_2nd.push_back(objMask_2nd[i]);
return;
}
// 亚像素定位核心算法
vector<Luma_offsetTestCompare> subpixel_localization(
const std::vector<Luma_rgnData> signal,
std::vector<double>& objMask_1st,
std::vector<double>& objMask_2nd,
std::vector<int>& nObjMask_1st,
std::vector<int>& nObjMask_2nd)
{
// 计算导数响应
std::vector<Luma_offsetTestCompare> subpixel;
for (int i = 0, i_max = signal.size(); i < i_max; i++)
{
double D = 0;
double D2 = 0;
int nD = 0;
int nD2 = 0;
for (int j = 0; j < LUMA_RGN_DATA_WIN_SIZE; j++)
{
D += (double)signal[i].data[j] * objMask_1st[j];
D2 += (double)signal[i].data[j] * objMask_2nd[j];
nD += (int)signal[i].data[j] * nObjMask_1st[j];
nD2 += (int)signal[i].data[j] * nObjMask_2nd[j];
}
Luma_offsetTestCompare a_sub;
a_sub.true_offset = signal[i].offset;
a_sub.compute_offset = D / D2;
a_sub.nCom_offset = (double)((float)nD / (float)nD2);
subpixel.push_back(a_sub);
}
return subpixel;
#if 0
vector<double> D = convolve(signal, mask_1st);
vector<double> D2 = convolve(signal, mask_2nd);
// 寻找候选点 (过零点)
vector<double> positions;
for (int i = 1; i < D.size() - 1; ++i) {
// 检测过零点
if (D[i] * D[i + 1] < 0 || D[i] * D[i - 1] < 0) {
// 亚像素插值
double x0 = D[i - 1];
double x1 = D[i];
double x2 = D[i + 1];
// 抛物线插值公式
double offset = 0.5 * (x0 - x2) / (x0 - 2 * x1 + x2);
double subpixel_pos = i + offset;
// 计算二阶导数验证
double d2_val = D2[i] + offset * (D2[i + 1] - D2[i]);
// 有效性检查 (排除弱响应)
if (fabs(d2_val) > 1e-3) {
positions.push_back(subpixel_pos);
}
}
}
return positions;
#endif
}
void _outputTestSample(char* fileName, std::vector<Luma_rgnData>& testSamples)
{
std::ofstream sw(fileName);
char str[250];
sprintf_s(str, "0x10");
sw << str << std::endl;
for (int i = 0, i_max = testSamples.size(); i < i_max; i++)
{
char data[250];
sprintf_s(data, "%04x %04x %04x %01x %02x",
testSamples[i].WinRdx, testSamples[i].y, testSamples[i].Rid, testSamples[i].Flag, testSamples[i].PeakRltvRdx);
sw << data << std::endl;
for (int j = 0; j < LUMA_RGN_DATA_WIN_SIZE; j++)
{
sprintf_s(data, "%02x", testSamples[i].data[j]);
sw << data << std::endl;
}
}
sw.close();
}
void _outputMaskData(char* fileName, double sigma, std::vector<double>& mask_1st, std::vector<double>& mask_2nd,
double scale, std::vector<int>& nMask_1st, std::vector<int>& nMask_2nd)
{
std::ofstream sw(fileName);
char str[250];
sprintf_s(str, "sigma=%f", sigma);
sw << str << std::endl;
sprintf_s(str, "mask_1st:");
sw << str << std::endl;
for (int i = 0, i_max = mask_1st.size(); i < i_max; i++)
{
if (i < i_max - 1)
sprintf_s(str, "%f, ", mask_1st[i]);
else
sprintf_s(str, "%f", mask_1st[i]);
sw << str;
}
sw << std::endl;
sprintf_s(str, "mask_2nd:");
sw << str << std::endl;
for (int i = 0, i_max = mask_2nd.size(); i < i_max; i++)
{
if (i < i_max - 1)
sprintf_s(str, "%f, ", mask_2nd[i]);
else
sprintf_s(str, "%f", mask_2nd[i]);
sw << str;
}
sw << std::endl;
sw << std::endl;
sprintf_s(str, "scale=%f", scale);
sw << str << std::endl;
sprintf_s(str, "nMask_1st:");
sw << str << std::endl;
for (int i = 0, i_max = nMask_1st.size(); i < i_max; i++)
{
if (i < i_max - 1)
sprintf_s(str, "%d, ", nMask_1st[i]);
else
sprintf_s(str, "%d", nMask_1st[i]);
sw << str;
}
sw << std::endl;
sprintf_s(str, "nMask_2nd:");
sw << str << std::endl;
for (int i = 0, i_max = nMask_2nd.size(); i < i_max; i++)
{
if (i < i_max - 1)
sprintf_s(str, "%d, ", nMask_2nd[i]);
else
sprintf_s(str, "%d", nMask_2nd[i]);
sw << str;
}
sw << std::endl;
sw.close();
return;
}
#pragma pack(push, 1)
typedef struct {
uint16_t file_type; // 文件类型,'BM'
uint32_t file_size; // 文件大小
uint16_t reserved1; // 保留字段
uint16_t reserved2;
uint32_t offset_data; // 数据偏移
}BMPFileHeader;
typedef struct {
uint32_t size; // 信息头大小40字节
int32_t width; // 图像宽度
int32_t height; // 图像高度(正数表示倒序)
uint16_t planes; // 颜色平面数必须为1
uint16_t bit_count; // 每像素位数24
uint32_t compression; // 压缩方式0表示无压缩
uint32_t size_image; // 像素数据大小
int32_t x_pixels_per_meter;
int32_t y_pixels_per_meter;
uint32_t colors_used;
uint32_t colors_important;
} BMPInfoHeader;
#pragma pack(pop)
void save_bmp(const char* filename, uint8_t* image_data, int width, int height) {
FILE* file;
fopen_s(&file, filename, "wb");
if (!file) {
std::printf("无法打开文件 %s\n", filename);
return;
}
// 计算每行填充字节数
int bytes_per_row = width * 3; // 每个像素3字节BGR
int padding = (4 - (bytes_per_row % 4)) % 4;
int row_size = bytes_per_row + padding;
// 初始化文件头
BMPFileHeader file_header = {
.file_type = 0x4D42, // 'BM'
.file_size = sizeof(BMPFileHeader) + sizeof(BMPInfoHeader) + row_size * height,
.reserved1 = 0,
.reserved2 = 0,
.offset_data = sizeof(BMPFileHeader) + sizeof(BMPInfoHeader)
};
// 初始化信息头
BMPInfoHeader info_header = {
.size = sizeof(BMPInfoHeader),
.width = width,
.height = height, // 正数表示像素数据从下到上排列
.planes = 1,
.bit_count = 24,
.compression = 0,
.size_image = (uint32_t)(row_size * height),
.x_pixels_per_meter = 0,
.y_pixels_per_meter = 0,
.colors_used = 0,
.colors_important = 0
};
// 写入头信息
fwrite(&file_header, 1, sizeof(BMPFileHeader), file);
fwrite(&info_header, 1, sizeof(BMPInfoHeader), file);
// 写入像素数据(从最后一行开始)
uint8_t padding_bytes[3] = { 0, 0, 0 };
for (int y = height - 1; y >= 0; y--) {
for (int x = 0; x < width; x++) {
uint8_t* pixel = image_data + (y * width + x) * 3;
// 将RGB转为BGR顺序
fputc(pixel[2], file); // B
fputc(pixel[1], file); // G
fputc(pixel[0], file); // R
}
fwrite(padding_bytes, 1, padding, file); // 填充
}
fclose(file);
}
void save_bmp_2(const char* filename, std::vector<Luma_rgnData>& testSamples) {
FILE* file;
fopen_s(&file, filename, "wb");
if (!file) {
std::printf("无法打开文件 %s\n", filename);
return;
}
// 计算每行填充字节数
int bytes_per_row = LUMA_RGN_DATA_WIN_SIZE * 3; // 每个像素3字节BGR
int padding = (4 - (bytes_per_row % 4)) % 4;
int row_size = bytes_per_row + padding;
int height = testSamples.size();
// 初始化文件头
BMPFileHeader file_header = {
.file_type = 0x4D42, // 'BM'
.file_size = sizeof(BMPFileHeader) + sizeof(BMPInfoHeader) + row_size * height,
.reserved1 = 0,
.reserved2 = 0,
.offset_data = sizeof(BMPFileHeader) + sizeof(BMPInfoHeader)
};
// 初始化信息头
BMPInfoHeader info_header = {
.size = sizeof(BMPInfoHeader),
.width = LUMA_RGN_DATA_WIN_SIZE,
.height = height, // 正数表示像素数据从下到上排列
.planes = 1,
.bit_count = 24,
.compression = 0,
.size_image = (uint32_t)(row_size * height),
.x_pixels_per_meter = 0,
.y_pixels_per_meter = 0,
.colors_used = 0,
.colors_important = 0
};
// 写入头信息
fwrite(&file_header, 1, sizeof(BMPFileHeader), file);
fwrite(&info_header, 1, sizeof(BMPInfoHeader), file);
// 写入像素数据(从最后一行开始)
uint8_t padding_bytes[3] = { 0, 0, 0 };
for (int y = height - 1; y >= 0; y--) {
for (int x = 0; x < LUMA_RGN_DATA_WIN_SIZE; x++) {
uint8_t pixel = (uint8_t)testSamples[y].data[x];
// 将RGB转为BGR顺序
fputc(pixel, file); // B
fputc(pixel, file); // G
fputc(pixel, file); // R
}
fwrite(padding_bytes, 1, padding, file); // 填充
}
fclose(file);
}
#if 0
// 示例使用
int main() {
const int WIDTH = 640;
const int HEIGHT = 480;
uint8_t image[HEIGHT][WIDTH][3]; // 假设图像数据为RGB格式
// 填充测试数据(红色)
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
image[y][x][0] = 255; // R
image[y][x][1] = 0; // G
image[y][x][2] = 0; // B
}
}
save_bmp("output.bmp", (uint8_t*)image, WIDTH, HEIGHT);
return 0;
}
void writeBMP(const char* filename, std::vector<Luma_rgnData>& testSamples)
{
std::ofstream file(filename, std::ios::out | std::ios::binary);
if (!file) return;
// BMP文件头结构体
struct BMPHeader {
uint16_t type; // Magic identifier
uint32_t size; // File size in bytes
uint16_t reserved1; // Not used
uint16_t reserved2; // Not used
uint32_t offset; // Start position of pixel data
uint32_t DIBSize; // DIB header size
int32_t width; // width of bitmap in pixels
int32_t height; // width of bitmap in pixels
uint16_t planes; // Number of color planes must be 1
uint16_t bits; // Bits per pixel
uint32_t compression; // Compression type
uint32_t imagesize; // Image size must be 0 for uncompressed images
int32_t xresolution; // Pixels per meter
int32_t yresolution; // Pixels per meter
uint32_t ncolor; // Number of colors
uint32_t importantcolor; // Number of important colors
} header;
header.type = 0x4D42; // 'BM' in little endian.
header.size = 54 + (width * height * 3); // header size + data size (3 bytes per pixel for RGB)
header.reserved1 = 0;
header.reserved2 = 0;
header.offset = 54; // Start of pixel data after the header.
header.DIBSize = 40; // Size of the DIB header, in bytes.
header.width = width;
header.height = height;
header.planes = 1; // Number of color planes. Must be set to 1.
header.bits = 24; // Bits per pixel (24 bits for RGB).
header.compression = 0; // BI_RGB, no compression used.
header.imagesize = (width * height * 3); // Image size, in bytes. Must be 0 for BI_RGB bitmaps.
header.xresolution = 0; // Pixels per meter (set to 0 to use default value).
header.yresolution = 0; // Pixels per meter (set to 0 to use default value).
header.ncolor = 0; // Number of colors in the color palette. Must be set to 0 for BI_RGB bitmaps.
header.importantcolor = 0; // All colors are important. Must be set to 0 for BI_RGB bitmaps.
file.write(reinterpret_cast<const char*>(&header), sizeof(header)); // Write the header to the file.
file.write(reinterpret_cast<const char*>(data), width * height * 3); // Write the pixel data to the file.
}
#endif
int main() {
#if 0
// 生成测试信号 (高斯峰位于15.3的位置)
vector<double> signal(30, 0.0);
double true_pos = 15.3;
double sigma = 3.0;
for (int i = 0; i < signal.size(); ++i) {
double x = i - true_pos;
signal[i] = exp(-x * x / (2 * sigma * sigma));
}
#endif
double sigmaValue[3] = { 2.0, 3.0, 4.0 };
double pkValue[10] = {20.0, 40.0, 60.0, 100.0, 200.0, 240.0, 250.0, 260.0, 280.0, 300.0};
int testId = 0;
std::vector<Luma_rgnData> testSamples;
// 参数设置
double width = 4;
double sigma = width / 1.5;
int radius = ceil(5 * sigma);
std::vector<double> objMask_1st;
std::vector<double> objMask_2nd;
_genSubpixMask(
sigma,
radius,
objMask_1st,
objMask_2nd);
double scale = 1024.0 * 1024.0 * 8;
std::vector<int> nObjMask_1st;
nObjMask_1st.resize(objMask_1st.size());
std::vector<int> nObjMask_2nd;
nObjMask_2nd.resize(objMask_2nd.size());
for (int i = 0; i < objMask_1st.size(); i++)
nObjMask_1st[i] = (int)(objMask_1st[i] * scale);
for (int i = 0; i < objMask_2nd.size(); i++)
nObjMask_2nd[i] = (int)(objMask_2nd[i] * scale);
for (int sidx = 0; sidx < 3; sidx++)
{
double sigma = sigmaValue[sidx];
for (int loop = 0; loop < 10; loop++)
{
std::vector<Luma_rgnData> testSignal = _genTestData(sigma, pkValue[loop]);
testSamples.insert(testSamples.end(), testSignal.begin(), testSignal.end());
// 执行亚像素定位
auto positions = subpixel_localization(testSignal, objMask_1st, objMask_2nd, nObjMask_1st, nObjMask_2nd);
for (int i = 0, i_max = positions.size(); i < i_max; i++)
{
cout << "Test_" << testId << ": ( ";
for (int j = 0; j < LUMA_RGN_DATA_WIN_SIZE - 1; j++)
cout << (int)testSignal[i].data[j] << ",";
cout << (int)testSignal[i].data[LUMA_RGN_DATA_WIN_SIZE - 1] << " )" ;
double diff = positions[i].compute_offset - positions[i].true_offset;
double diff2 = positions[i].compute_offset - positions[i].nCom_offset;
cout << " true_offset=" << positions[i].true_offset << " pos=" << positions[i].compute_offset << " nComPos=" << positions[i].nCom_offset << " diff=" << diff << " diff2=" << diff2 << std::endl;
testId++;
}
}
}
//文件输出
char outFile[250];
sprintf_s(outFile, "F:\\上古\\相机开发\\测试数据\\testSampe.txt");
_outputTestSample(outFile, testSamples);
sprintf_s(outFile, "F:\\上古\\相机开发\\测试数据\\testSampe.bmp");
save_bmp_2(outFile, testSamples);
sprintf_s(outFile, "F:\\上古\\相机开发\\测试数据\\maskData.txt");
_outputMaskData(outFile, sigma, objMask_1st, objMask_2nd, scale, nObjMask_1st, nObjMask_2nd);
std::printf("done!\n");
#if 0
// 输出结果
cout << "True position: " << true_pos << endl;
cout << "Detected positions:\n";
for (double p : positions) {
cout << p << " (error: " << fabs(p - true_pos) << ")\n";
}
#endif
return 0;
}