/* 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(j, i); /* 定点化 */ pMeshXY[xIdxMesh] = (unsigned short)xVal; pMeshXY[xIdxMesh + 1] = (unsigned short)((xVal - (unsigned short)xVal) * 256); yVal = mapyBig.at(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(i, j) < 0) { mapxBig.at(i, j) = 0; } if (mapyBig.at(i, j) < 0) { mapyBig.at(i, j) = 0; } if (mapxBig.at(i, j) > (srcW - 3)) { mapxBig.at(i, j) = (srcW - 3); }/* 这里注意需要在右侧和下侧边界做限制 */ if (mapyBig.at(i, j) > (srcH - 3)) { mapyBig.at(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_(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(b, a); // 限制边界 xVal = xVal > 0 ? xVal : 0; xVal = xVal < (srcW - 1) ? xVal : (srcW - 1); //mapX.at(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_(srcH, srcW); for (int i = 0; i < srcH; i++) { for (int j = 0; j < srcW; j++) { mapxBig.at(i, j) = j;/* 这里以生成无校正效果的全表为例 */ if (mapxBig.at(i, j) < 0) { mapxBig.at(i, j) = 0; } /* 注意不要超出图像坐标范围 */ if (mapxBig.at(i, j) > (srcW - 1)) { mapxBig.at(i, j) = (srcW - 1); } } } /* 生成LDCH的mesh表 */ char *ldchMeshPath = "../data_out/ldch_meshx.bin"; mapBig2LdchMesh(mapxBig, srcW, srcH, ldchMeshPath); }