You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

297 lines
9.5 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
1) 大表cv::Mat格式转FEC的4个小表xi,xf,yi,yf
*/
void mapBig2FecMesh(cv::Mat &mapxBig, cv::Mat &mapyBig, int srcW, int srcH, const char *fecMeshPath)
{
/* 希望得到的校正后的目标图像dst的宽高 */
int dstW = srcW;
int dstH = srcH;
/* dst图像宽高扩展对齐 */
int dstW_ex = 32 * ((dstW + 31) / 32);
int dstH_ex = 32 * ((dstH + 31) / 32);
/* dst图像对应的映射表的步长 */
int meshStepW, meshStepH;
if (dstW > 1920) { //32x16
meshStepW = 32;
meshStepH = 16;
}
else { //16x8
meshStepW = 16;
meshStepH = 8;
}
/* dst图像对应的映射表的宽高 */
int meshSizeW = (dstW_ex + meshStepW - 1) / meshStepW + 1;
int meshSizeH = (dstH_ex + meshStepH - 1) / meshStepH + 1;
/* dst图像对应的FEC mesh的数据大小 */
int dstFecMeshSize = meshSizeW * meshSizeH * 2 * 2;
/* 申请FEC mesh的内存 */
unsigned short *pMeshXY = new unsigned short[dstFecMeshSize];
double xVal = 0;
double yVal = 0;
/* FEC mesh的index */
int xIdxMesh = 0;
int yIdxMesh = meshSizeW * meshSizeH * 2;
/* 大表降采样为dst图像对应的FEC mesh */
for (int j = 0; j <= dstH_ex; j = j + meshStepH)
{
for (int i = 0; i <= dstW_ex; i = i + meshStepW)
{
if (j == dstH_ex)
{
j = dstH_ex - 1;
}
if (i == dstW_ex)
{
i = dstW_ex - 1;
}
xVal = mapxBig.at<double>(j, i);
/* 定点化 */
pMeshXY[xIdxMesh] = (unsigned short)xVal;
pMeshXY[xIdxMesh + 1] = (unsigned short)((xVal - (unsigned short)xVal) * 256);
yVal = mapyBig.at<double>(j, i);
/* 定点化 */
pMeshXY[yIdxMesh] = (unsigned short)yVal;
pMeshXY[yIdxMesh + 1] = (unsigned short)((yVal - (unsigned short)yVal) * 256);
xIdxMesh += 2;
yIdxMesh += 2;
}
}
/* 计算4个mesh的相关参数 */
unsigned short SpbMeshPNum = 128 / meshStepH * meshSizeW;
unsigned long MeshNumW;
int LastSpbH;
unsigned short SpbNum = (dstH + 128 - 1) / 128;
MeshNumW = dstW_ex / meshStepW;
unsigned long MeshPointNumW = MeshNumW + 1;
unsigned short SpbMeshPNumH = 128 / meshStepH + 1;
LastSpbH = (dstH_ex % 128 == 0) ? 128 : (dstH_ex % 128);
unsigned short LastSpbMeshPNumH = LastSpbH / meshStepH + 1;
/* 4个mesh的大小 */
int meshSize4bin = (SpbNum - 1) * MeshPointNumW * SpbMeshPNumH + MeshPointNumW * LastSpbMeshPNumH;
unsigned short *pMeshXI = new unsigned short[meshSize4bin]; /* X整数部分 */
unsigned char *pMeshXF = new unsigned char[meshSize4bin]; /* X小数部分 */
unsigned short *pMeshYI = new unsigned short[meshSize4bin]; /* Y整数部分 */
unsigned char *pMeshYF = new unsigned char[meshSize4bin]; /* Y小数部分 */
unsigned short *pTmpXi = (unsigned short *)&pMeshXY[0];
unsigned short *pTmpXf = (unsigned short *)&pMeshXY[1];
unsigned short *pTmpYi = (unsigned short *)&pMeshXY[meshSizeW * meshSizeH * 2];
unsigned short *pTmpYf = (unsigned short *)&pMeshXY[meshSizeW * meshSizeH * 2 + 1];
unsigned short *pTmpXI = new unsigned short[meshSizeW * meshSizeH];
unsigned char *pTmpXF = new unsigned char[meshSizeW * meshSizeH];
unsigned short *pTmpYI = new unsigned short[meshSizeW * meshSizeH];
unsigned char *pTmpYF = new unsigned char[meshSizeW * meshSizeH];
for (int i = 0; i < meshSizeW * meshSizeH; ++i) {
pTmpXI[i] = *pTmpXi; pTmpXi += 2;
pTmpXF[i] = (unsigned char)*pTmpXf; pTmpXf += 2;
pTmpYI[i] = *pTmpYi; pTmpYi += 2;
pTmpYF[i] = (unsigned char)*pTmpYf; pTmpYf += 2;
}
unsigned long OutIdx = 0;
unsigned long InIdx = 0;
unsigned short mesh_blkh;
unsigned short ColMeshPNum = meshSizeW;
unsigned short RowMeshPNum = meshSizeH;
for (int spb_cnt = 0; spb_cnt < SpbNum; ++spb_cnt) {
mesh_blkh = (spb_cnt == SpbNum - 1) ? LastSpbMeshPNumH : SpbMeshPNumH;
for (int j = 0; j < MeshPointNumW; ++j) {
for (int i = 0; i < mesh_blkh; ++i) {
unsigned long IdxC = MIN(j, ColMeshPNum - 1);
unsigned long IdxR = MIN((spb_cnt*(128 / meshStepH) + i), RowMeshPNum - 1);
InIdx = IdxR * ColMeshPNum + IdxC;
pMeshXI[OutIdx] = pTmpXI[InIdx];
pMeshXF[OutIdx] = pTmpXF[InIdx];
pMeshYI[OutIdx] = pTmpYI[InIdx];
pMeshYF[OutIdx] = pTmpYF[InIdx];
++OutIdx;
}
}
}
/* 内存释放 */
delete[] pTmpXI;
delete[] pTmpXF;
delete[] pTmpYI;
delete[] pTmpYF;
char meshxiName[256]; strcpy(meshxiName, fecMeshPath); strcat(meshxiName, "meshxi.bin");
FILE* fp_meshxi = fopen(meshxiName, "wb");
char meshxfName[256]; strcpy(meshxfName, fecMeshPath); strcat(meshxfName, "meshxf.bin");
FILE* fp_meshxf = fopen(meshxfName, "wb");
char meshyiName[256]; strcpy(meshyiName, fecMeshPath); strcat(meshyiName, "meshyi.bin");
FILE* fp_meshyi = fopen(meshyiName, "wb");
char meshyfName[256]; strcpy(meshyfName, fecMeshPath); strcat(meshyfName, "meshyf.bin");
FILE* fp_meshyf = fopen(meshyfName, "wb");
if (fp_meshxi == NULL || fp_meshxf == NULL || fp_meshyi == NULL || fp_meshyf == NULL)
{
printf("save FEC 4 Mesh.bin error!!!\n");
return;
}
fwrite(pMeshXI, sizeof(unsigned short), meshSize4bin, fp_meshxi);
fwrite(pMeshXF, sizeof(unsigned char), meshSize4bin, fp_meshxf);
fwrite(pMeshYI, sizeof(unsigned short), meshSize4bin, fp_meshyi);
fwrite(pMeshYF, sizeof(unsigned char), meshSize4bin, fp_meshyf);
fclose(fp_meshxi);
fclose(fp_meshxf);
fclose(fp_meshyi);
fclose(fp_meshyf);
/* 内存释放 */
delete[] pMeshXY;
delete[] pMeshXI;
delete[] pMeshXF;
delete[] pMeshYI;
delete[] pMeshYF;
}
void test1()
{
/* 输入图像真实宽高 */
int srcW = 1280;
int srcH = 1072;
/* 输入图像宽高32对齐 */
int srcW_ex = 32 * ((srcW + 31) / 32);
int srcH_ex = 32 * ((srcH + 31) / 32);
// 使用opencv生成全分辨率的表表的宽高设置需要对齐
cv::Size imageSize = cv::Size(srcW_ex, srcH_ex);
cv::Mat mapxBig, mapyBig;
cv::initUndistortRectifyMap(camMatrix, distCoeffs, R, newCamMatrix, imageSize, CV_32FC1, mapxBig, mapyBig); // 这个函数只能生成float32类型的数据
mapxBig.convertTo(mapxBig, CV_64FC1);// 所以这里需要转为float64类型
mapyBig.convertTo(mapyBig, CV_64FC1);
for (int i = 0; i < srcH_ex; i++)
{
for (int j = 0; j < srcW_ex; j++)
{
if (mapxBig.at<double>(i, j) < 0) { mapxBig.at<double>(i, j) = 0; }
if (mapyBig.at<double>(i, j) < 0) { mapyBig.at<double>(i, j) = 0; }
if (mapxBig.at<double>(i, j) > (srcW - 3)) { mapxBig.at<double>(i, j) = (srcW - 3); }/* 这里注意需要在右侧和下侧边界做限制 */
if (mapyBig.at<double>(i, j) > (srcH - 3)) { mapyBig.at<double>(i, j) = (srcH - 3); }
}
}
/* 生成FEC的4个mesh小表 */
char *fecMeshPath = "../data_out/";
mapBig2FecMesh(mapxBig, mapyBig, srcW, srcH, fecMeshPath);
}
/*
1) 大表cv::Mat格式转LDCH的小表
*/
void mapBig2LdchMesh(cv::Mat &mapxBig, int srcW, int srcH, const char *ldchMeshPath)
{
int map_scale_bit_X = 4; /* Map表宽度下采样bit数 */
int map_scale_bit_Y = 3; /* Map表高度下采样bit数 */
/* 定点化左移位数 */
int mapxFixBit = 4;
if (srcW > 4096)
{
mapxFixBit = 3;
}
/* mesh表的宽 */
int meshSizeW = ((srcW + (1 << map_scale_bit_X) - 1) >> map_scale_bit_X) + 1;
/* mesh表的高 */
int meshSizeH = ((srcH + (1 << map_scale_bit_Y) - 1) >> map_scale_bit_Y) + 1;
/* mesh表降采样的步长 */
double meshStepW = double(srcW) / double(meshSizeW - 1);
double meshStepH = double(srcH) / double(meshSizeH - 1);
/* 对齐后的宽 */
int mapWidAlign = ((meshSizeW + 1) >> 1) << 1;
int meshSize = mapWidAlign * meshSizeH;
unsigned short *pMeshX = new unsigned short[meshSize];
double xVal = 0;
int a = 0, b = 0;
double mapxtmp;
unsigned short tmpi;
int indexX = 0;
bool doAlign = (meshSizeW % 2) != 0; /* 每行做2对齐*/
//cv::Mat mapX = cv::Mat_<double>(meshSizeH, meshSizeW);/* 查看网格用的 */
for (int j = 0; j < meshSizeH; ++j, b = b + meshStepH)
{
a = 0;
for (int i = 0; i < meshSizeW; ++i, a = a + meshStepW)
{
if (a > srcW - 1) { a = srcW - 1; }
if (b > srcH - 1) { b = srcH - 1; }
xVal = mapxBig.at<double>(b, a);
// 限制边界
xVal = xVal > 0 ? xVal : 0;
xVal = xVal < (srcW - 1) ? xVal : (srcW - 1);
//mapX.at<double>(j, i) = xVal;
mapxtmp = xVal;
tmpi = mapxtmp * (1 << mapxFixBit);
pMeshX[indexX] = tmpi;
++indexX;
}
/* 每行做2对齐*/
if (doAlign)
{
pMeshX[indexX] = 0;
++indexX;
}
}
/* 将MeshX保存为bin文件 */
FILE *fpMeshX = fopen(ldchMeshPath, "wb");
if (fpMeshX == NULL)
{
printf("save LDCH MeshX.bin open error!!!");
return;
}
fwrite(&srcW, sizeof(unsigned short), 1, fpMeshX);
fwrite(&srcH, sizeof(unsigned short), 1, fpMeshX);
fwrite(&mapWidAlign, sizeof(unsigned short), 1, fpMeshX);
fwrite(&meshSizeH, sizeof(unsigned short), 1, fpMeshX);
fwrite(&meshStepW, sizeof(unsigned short), 1, fpMeshX);
fwrite(&meshStepH, sizeof(unsigned short), 1, fpMeshX);
fwrite(pMeshX, sizeof(unsigned short), meshSize, fpMeshX);
fclose(fpMeshX);
delete[] pMeshX;
}
void test2()
{
/* 输入图像真实宽高 */
int srcW = 2688;
int srcH = 1520;
/* 需要客户自己生成原分辨率的校正表mapxBig, 为了方便说明,以下用opencv的数据cv::Mat来表示全表,客户也可以用其他形式,如二维数组等 */
cv::Mat mapxBig = cv::Mat_<double>(srcH, srcW);
for (int i = 0; i < srcH; i++)
{
for (int j = 0; j < srcW; j++)
{
mapxBig.at<double>(i, j) = j;/* 这里以生成无校正效果的全表为例 */
if (mapxBig.at<double>(i, j) < 0) { mapxBig.at<double>(i, j) = 0; } /* 注意不要超出图像坐标范围 */
if (mapxBig.at<double>(i, j) > (srcW - 1)) { mapxBig.at<double>(i, j) = (srcW - 1); }
}
}
/* 生成LDCH的mesh表 */
char *ldchMeshPath = "../data_out/ldch_meshx.bin";
mapBig2LdchMesh(mapxBig, srcW, srcH, ldchMeshPath);
}