/// <summary> /// 通过插值经纬度数据,生成查找表 /// 线性外插:从实际情况看,不需要执行这个线性外插,即可消除bow-tie弯弓效应。即:每个整扫描带跳过最后一行的插值。 /// 目前局部数据看到的情况是,Fy3AMERSI的原始数据已经处理了bow-tie,FY3B和FY3C的没处理。 /// 本插值仅适用于经纬度放大的情况,比如放大1倍,放大两倍等等。 /// </summary> /// <param name="srcToDstProjXs"></param> /// <param name="srcToDstProjYs"></param> /// <param name="srcJdSize"></param> /// <param name="srcDataSize"></param> /// <param name="dstDataSize"></param> /// <param name="dstEnvelope"></param> /// <param name="rowMapTable"></param> /// <param name="colMapTable"></param> /// <param name="progressCallback"></param> /// <param name="scanLineWidth"></param> public void ComputeIndexMapTable(double[] srcToDstProjXs, double[] srcToDstProjYs, Size srcJdSize, Size srcDataSize, Size dstDataSize, PrjEnvelope dstEnvelope, out UInt16[] rowMapTable, out UInt16[] colMapTable, Action <int, string> progressCallback, int scanLineWidth) { int dstHeight = dstDataSize.Height; int dstWidth = dstDataSize.Width; int srcHeight = srcJdSize.Height; int srcWidth = srcJdSize.Width; int srcDataWidth = srcDataSize.Width; int srcDataHeight = srcDataSize.Height; int srcLength = srcWidth * srcHeight; int srcDataLength = srcDataWidth * srcDataHeight; int dstLength = dstWidth * dstHeight; double dstResolutionsX = dstEnvelope.Width / dstWidth; double dstResolutionsY = dstEnvelope.Height / dstHeight; int slopeX = srcDataWidth / srcWidth; //4,2 int slopeY = srcDataHeight / srcHeight; //4,2 double dstMinX = dstEnvelope.MinX; double dstMaxX = dstEnvelope.MaxX; double dstMaxY = dstEnvelope.MaxY; double dstMinY = dstEnvelope.MinY; double srcValidMinX = dstEnvelope.MinX - dstResolutionsX * slopeX * 2; double srcValidMaxX = dstEnvelope.MaxX + dstResolutionsX * slopeX; double srcValidMaxY = dstEnvelope.MaxY + dstResolutionsY * slopeY * 2; double srcValidMinY = dstEnvelope.MinY - +dstResolutionsY * slopeY; float factorX = (float)srcWidth / srcDataWidth; //1/4;1/2 float factorY = (float)srcHeight / srcDataHeight; //1/4;1/2 byte[] lootUpTableTag = new byte[dstLength]; // UInt16[] tmpRowLookUpTable = new UInt16[dstLength]; // UInt16[] tmpColLookUpTable = new UInt16[dstLength]; // if (InvalidValue != 0) { for (int i = 0; i < dstLength; i++) { tmpRowLookUpTable[i] = InvalidValue; tmpColLookUpTable[i] = InvalidValue; } } //扫描带宽度:10//用于去除 Parallel.For(0, srcHeight, (oldRow) => //oldRow、oldCol插值前的行,列 { if (scanLineWidth > 1 && (oldRow + 1) % scanLineWidth == 0) //每条扫描线的最后一行。 { } else //线性内插 { int destRowIndex, destColIndex; int destIndex; double curX, curY; int dstCol; float oldRowF, oldColF; int newRow, newCol; int dstRow; int rowOffset = oldRow * srcWidth; int srcIndex; double srcX, srcY; //临时存储插后的经纬度数据集 double[,] m_fTempLat = new double[slopeX, slopeY]; double[,] m_fTempLon = new double[slopeX, slopeY]; double p1, p2, p3, p4; int v1, v2, v3, v4; double pu1; int vSrcWidth; int v1SrcWidth; int i, j; double v, u; //下面用双线性差值计算出放大后的经纬度(XY)值,公式如下: //f(i+u,j+v)=(1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1); //p1=(1-u)(1-v),p2=(1-u)v,p3=u * (1 - v),p4=u * v // for (int oldCol = 0; oldCol < srcWidth; oldCol++) { srcIndex = rowOffset + oldCol; srcX = srcToDstProjXs[srcIndex]; srcY = srcToDstProjYs[srcIndex]; if (srcY <= srcValidMaxY && srcY >= srcValidMinY && srcX >= srcValidMinX && srcX <= srcValidMaxX) { newRow = oldRow * slopeX; //记录插值后的行列号 newCol = oldCol * slopeX; //下面使用双线性插值,插值放大后的区域的值 for (int blockRow = 0; blockRow < slopeY; blockRow++) { dstRow = blockRow + newRow; //目标行 oldRowF = dstRow * factorY; i = (int)oldRowF; if (i > oldRowF) { --i; //x = (long)Math.Floor(fx);//取最大整数 } u = oldRowF - i; pu1 = 1 - u; vSrcWidth = i * srcWidth; v1SrcWidth = (i + 1) * srcWidth; for (int blockCol = 0; blockCol < slopeX; blockCol++) { dstCol = blockCol + newCol; //目标列 oldColF = dstCol * factorX; j = (int)oldColF; if (j > oldColF) { --j; } v = oldColF - j; if (i >= srcHeight - 1 && j >= srcWidth - 1) //>=最后一行,并且>=最后一列 { v1 = vSrcWidth + j; p1 = pu1 * (1 - v); m_fTempLon[blockRow, blockCol] = p1 * srcToDstProjXs[v1]; m_fTempLat[blockRow, blockCol] = p1 * srcToDstProjYs[v1]; } else if (i >= srcHeight - 1) //最后一行 { p1 = pu1 * (1 - v); p2 = pu1 * v; v1 = vSrcWidth + j; v2 = vSrcWidth + j + 1; m_fTempLon[blockRow, blockCol] = p1 * srcToDstProjXs[v1] + p2 * srcToDstProjXs[v2]; m_fTempLat[blockRow, blockCol] = p1 * srcToDstProjYs[v1] + p2 * srcToDstProjYs[v2]; } else if (j >= srcWidth - 1) //最后一列 { p1 = pu1 * (1 - v); p3 = u * (1 - v); v1 = vSrcWidth + j; v3 = v1SrcWidth + j; m_fTempLon[blockRow, blockCol] = p1 * srcToDstProjXs[v1] + p3 * srcToDstProjXs[v3]; m_fTempLat[blockRow, blockCol] = p1 * srcToDstProjYs[v1] + p3 * srcToDstProjYs[v3]; } else //其他位置,双线性插值。 { p1 = pu1 * (1 - v); p2 = pu1 * v; p3 = u * (1 - v); p4 = u * v; v1 = vSrcWidth + j; v2 = vSrcWidth + j + 1; v3 = v1SrcWidth + j; v4 = v1SrcWidth + j + 1; m_fTempLon[blockRow, blockCol] = p1 * srcToDstProjXs[v1] + p2 * srcToDstProjXs[v2] + p3 * srcToDstProjXs[v3] + p4 * srcToDstProjXs[v4]; m_fTempLat[blockRow, blockCol] = p1 * srcToDstProjYs[v1] + p2 * srcToDstProjYs[v2] + p3 * srcToDstProjYs[v3] + p4 * srcToDstProjYs[v4]; } } } //计算查找表,将上面插好值的经纬度数据集映射到查找表 for (int blockRow = 0; blockRow < slopeY; blockRow++) { for (int blockCol = 0; blockCol < slopeX; blockCol++) { curX = m_fTempLon[blockRow, blockCol]; curY = m_fTempLat[blockRow, blockCol]; if (curY <= dstMaxY && curY >= dstMinY && curX >= dstMinX && curX <= dstMaxX) { destRowIndex = (int)((dstMaxY - curY) / dstResolutionsY); //Y方向计算出目标行 destColIndex = (int)((curX - dstMinX) / dstResolutionsX); //X方向计算出目标列 destIndex = destRowIndex * dstWidth + destColIndex; if (lootUpTableTag[destIndex] == 0 && destRowIndex < dstHeight && destRowIndex >= 0 && destColIndex < dstWidth && destColIndex >= 0) { tmpRowLookUpTable[destIndex] = (UInt16)(oldRow * slopeX + blockRow); tmpColLookUpTable[destIndex] = (UInt16)(oldCol * slopeY + blockCol); lootUpTableTag[destIndex] = 1; } } } } } } } } ); Interpolation.ChazhiNear(lootUpTableTag, dstDataSize.Width, dstDataSize.Height, tmpRowLookUpTable, tmpColLookUpTable); rowMapTable = tmpRowLookUpTable; colMapTable = tmpColLookUpTable; lootUpTableTag = new byte[1]; lootUpTableTag = null; }
/* * /// <summary> * /// 这里的srcXs,srcYs是源参考投影(srcSpatialRef)下的值。 * /// </summary> * public void ComputeIndexMapTable(SpatialReference srcSpatialRef, double[] srcXs, double[] srcYs, Size srcSize, * SpatialReference dstSpatialRef, Size dstSize, PrjEnvelope dstEnvelope, * out UInt16[] rowMapTable, out UInt16[] colMapTable, Action<int, string> progressCallback) * { * PrjEnvelope maxDstEnvelope; * ComputeDstEnvelope(srcSpatialRef, srcXs, srcYs, srcSize, dstSpatialRef, out maxDstEnvelope, progressCallback); * ComputeIndexMapTable(srcXs, srcYs, srcSize, dstSize, dstEnvelope, maxDstEnvelope, * out rowMapTable, out colMapTable, progressCallback); * } */ /// <summary> /// 这里的srcToDstSpatialXs,srcToDstSpatialYs是目标参考投影(dstSpatialRef)下的值 /// </summary> public void ComputeIndexMapTable(double[] srcToDstSpatialXs, double[] srcToDstSpatialYs, Size srcSize, Size dstSize, PrjEnvelope dstEnvelope, PrjEnvelope maxDstEnvelope, out UInt16[] rowMapTable, out UInt16[] colMapTable, Action <int, string> progressCallback) { if (!maxDstEnvelope.IntersectsWith(dstEnvelope)) { throw new Exception("目标坐标数据不在指定区域范围内"); } double dstMinX = dstEnvelope.MinX; double dstMaxX = dstEnvelope.MaxX; double dstMaxY = dstEnvelope.MaxY; double dstMinY = dstEnvelope.MinY; double dstResolutionsX = dstEnvelope.Width / dstSize.Width; double dstResolutionsY = dstEnvelope.Height / dstSize.Height; int srcLength = srcSize.Width * srcSize.Height; int dstLength = dstSize.Width * dstSize.Height; int dstHeight = dstSize.Height; int dstWidth = dstSize.Width; int srcHeight = srcSize.Height; int srcWidth = srcSize.Width; byte[] lootUpTableTag = new byte[dstLength]; //投影蒙板,用于图像内外标识(0:外部,1:内部) UInt16[] tmpRowLookUpTable = new UInt16[dstLength]; UInt16[] tmpColLookUpTable = new UInt16[dstLength]; if (InvalidValue != 0) { for (int i = 0; i < dstLength; i++) { tmpRowLookUpTable[i] = InvalidValue; tmpColLookUpTable[i] = InvalidValue; } } int srcValidLeft = 0; int srcValidRight = srcWidth; Parallel.For((int)0, srcHeight, (j) => { int srcIndex = 0; int dstIndex = 0; //目标位置 int dstJ; //目标行 int dsti; //目标列 double curX, curY; for (int i = srcValidLeft; i < srcValidRight; i++) { srcIndex = (j * srcWidth + i); curX = srcToDstSpatialXs[srcIndex]; curY = srcToDstSpatialYs[srcIndex]; dstJ = (int)((dstMaxY - curY) / dstResolutionsY + 0.5); //Y方向计算出目标行 索引从0开始所以-1 dsti = (int)((curX - dstMinX) / dstResolutionsX + 0.5); //X方向计算出目标列 if (dstJ >= 0 && dstJ < dstHeight && dsti >= 0 && dsti < dstWidth) { dstIndex = dstJ * dstWidth + dsti; tmpRowLookUpTable[dstIndex] = (UInt16)j; tmpColLookUpTable[dstIndex] = (UInt16)i; lootUpTableTag[dstIndex] = 1; } } }); if (dstSize.Width >= 2 && dstSize.Height >= 2) { Interpolation.ChazhiNear(lootUpTableTag, dstSize.Width, dstSize.Height, tmpRowLookUpTable, tmpColLookUpTable); } rowMapTable = tmpRowLookUpTable; colMapTable = tmpColLookUpTable; lootUpTableTag = new byte[1]; lootUpTableTag = null; }