camAlgo/HessianTable/HessianTable.cpp

818 lines
27 KiB
C++
Raw Normal View History

2025-08-16 15:25:29 +08:00
// 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;
}