logo资料库

双线性插值算法.pdf

第1页 / 共10页
第2页 / 共10页
第3页 / 共10页
第4页 / 共10页
第5页 / 共10页
第6页 / 共10页
第7页 / 共10页
第8页 / 共10页
资料共10页,剩余部分请下载后查看
双线性插值算法 图像的双线性插值放大算法中,目标图像中新创造的象素值,是由源图像位 置在它附近的 2*2 区域 4 个邻近象素的值通过加权平均计算得出的。双线性内插 值算法放大后的图像质量较高,不会出现像素值不连续的的情况。然而次算法具 有低通滤波器的性质,使高频分量受损,所以可能会使图像轮廓在一定程度上变 得模糊。 图 1 X 方向的线性插值 对于标准的双线性差值算法,X 方向的线性插值: [通用 1] [通用 2] 具体到我们所实现的算法中,我们使 Q11、Q12、Q21、Q22 为光栅上相邻的 四点,即 P 只能落于这四点其中一点上。∆col 是当前像素离像素所属区域原点的
水平距离,比如图 2,各种不同的颜色代表一个区域,区域原点为区域左上角的 像素。 δ R2 = Color Q22 − Color Q12 ∙ ∆col + Color Q12 ∙ 256 (1) δ R1 = Color Q21 − Color Q11 ∙ ∆col + Color Q11 ∙ 256 (2) 其中:∆col = (DestColNumber ∙ ((SrcWidth ≪ 8)/DestWidth))&255, Color(X)表示点 X 的颜色,具体算法使用的是 24 位真彩色格式。 Y 方向的线性插值 做完 X 方向的插值后再做 Y 方向的插值,对于一般情况,有: [通用 3] 而我们的具体算法中,Y 方向的线性插值方法如(3)所示。∆row 是当前像素离 像素所属区域原点的垂直距离,比如图 2,各种不同的颜色代表一个区域,区域 原点为区域左上角的像素。 Color P = δ R2 ∙ 256 + δ R2 − δ R1 ∙ ∆row ≫ 16 (3) 其中:∆row = (DestRowNumber ∙ ((SrcHeight ≪ 8)/DestHeight))&255,由于前 面为了便于计算左移了 16 位,因此最后需要右移 16 位保持匹配。 算法描述 for (目标图像第一行的像素++) { // 源图像上 Q12, Q22, Q11, Q21 的选取见下一节 获取源图像 Q12, Q22, Q11, Q21 的颜色; // X 方向的插值 δ(R2) = (Color(Q22) - Color(Q12)) * ∆col + Color(Q12) * 256; δ(R1) = (Color(Q21) - Color(Q11)) * ∆col + Color(Q11) * 256; // 保存 δ (R1)到一个临时数组,因为下一行的δ (R2)等于这一行的δ (R1) temp[i++] = δ(R1);
// Y 方向的插值 Color(P) = (δ(R2) * 256 + (δ(R2) - δ(R1)) *∆row ) >> 16; 将 P 输出到目标位图中。 } for (目标图像第二行到最末行) { for (行上的像素++) { // 源图像上 Q12, Q22, Q11, Q21 的选取见下一节 获取源图像 Q12, Q22, Q11, Q21 的颜色; // X 方向的插值 δ (R2) = temp[i++]; // 下一行的δ (R2)等于上一行的δ (R1) δ(R1) = (Color(Q21) - Color(Q11)) *∆col + Color(Q11) * 256; // 保存 δ (R1)到一个临时数组,因为下一行的δ (R2)等于这一行的δ (R1) temp[i++] = δ(R1); // Y 方向的插值 Color(P) = (δ(R2) * 256 + (δ(R2) - δ(R1)) * ∆row ) >> 16; 将 P 输出到目标位图中。 } } 算法中 Q12, Q22, Q11, Q21 的选取 我们以放大两倍为例,说明选取 Q12, Q22, Q11, Q21 的过程。源图像 3*3 区域放 大为目标区域 6*6 区域。设以下为目标图像: A A A A B B C C B B C C D D D D 图 2
目标图像 A 像素区域对应的 Q21,Q22,Q11,Q12,以红色区域为原点向右下 方扩展的 2*2 区域。 Q21 Q22 Q11 Q12 图 3 目标图像 B 像素区域对应的 Q21,Q22,Q11,Q12,以蓝色区域为原点向右下 方扩展的 2*2 区域。 Q21 Q22 Q11 Q12 图 4 目标图像 C 像素区域对应的 Q21,Q22,Q11,Q12,以绿色区域为原点向右下 方扩展的 2*2 区域。 Q21 Q22 Q11 Q12 图 5 目标图像 D 像素区域对应的 Q21,Q22,Q11,Q12,目标图像处于最后两行的 边界情况,将 Q21,Q22,Q11,Q12 这四个点的值设为一样。 Q11=Q12=Q22=Q21 图 6 程序流程图 流程图右边虚线框中为相关过程的注解。
输入目标位图 的高度和宽度 创建目标位图 计 算 放 大 / 缩 小比例 计算 Q21 的列 号 计算 Q21 位置 获取 Q21 的颜 色 Q21 未落在 源图像末行 Y N scaleH = (原图像宽度 << 8) / 目标 图像宽度; scaleV = (原图像高度 << 8) / 目标 图像高度; scaleH 为水平比例,scaleV 为垂直比 例。 PixelColAddr = 目标图像像素列号 * scaleH; ColDelta = PixelColAddr & 255; Q21 的 列 号 = (PixelColAddr - ColDelta) >> 8; 这样即可巧妙地根据不同的放大/缩 小比例计算出 Q21 的列号。 PixelColAddr 反应了目标位图上当 前像素离图像原点的水平偏离度。 ColDelta 反应了目标位图上当前像 素离区域原点的水平偏离度。 获取 Q11、Q12、 Q22 颜色 Q11 、 Q12 、 Q22 等于 Q21 的颜色 X 方向插值 Y 方向插值 将 像 素 值 输 出 到目标位图 下一个像素 Y 首 行 像 素 未到末尾 N InterQ21andQ22 = ColDelta * (Q22 颜色 – Q21 颜色) + Q21 颜色 * 256; InterQ11andQ12 = ColDelta * (Q12 颜色 – Q11 颜色) + Q11 颜色 * 256; InterTemp[i++] = InterQ11andQ12; 对于真彩色位图,应该分别对每个像 素的 G、B、R 的值进行处理。 目标像素的值 = (InterQ21andQ22 * 256 + (InterQ11andQ12 - InterQ21andQ22) * RowDelta) >> 16; 对于真彩色位图,应该分别对每个像 素的 G、B、R 的值进行处理。 RowDelta 反应了目标位图上当前像 素离区域原点的垂直偏离度。
计算 Q21 行号 计算 Q21 列号 计算 Q21 位置 获取 Q21 的颜 色 Q21 未落在 源图像末行 Y N 获取 Q11、Q12、 Q22 颜色 Q11 、 Q12 、 Q22 等于 Q21 的颜色 X 方向插值 Y 方向插值 将 像 素 值 输 出 到目标位图 下一个像素 Y Y 目 标 图 像 未到列末 N 目 标 图 像 未到行末 i = 0; PixelRowAddr =目标图像像素行号* scaleV; RowDelta = PixelRowAddr & 255; Q21 的 行 号 = (PixelRowAddr - RowDelta) >> 8; 这样即可巧妙地根据不同的放大/缩 小比例计算出 Q21 的行号。 辅助数组 InterTemp 的下标 i 归零。 PixelRowAddr 反应了目标位图上当 前像素离图像原点垂直偏离度。 RowDelta 反应了目标位图上当前像 素离区域原点的垂直偏离度。 PixelColAddr = 目标图像像素列号 * scaleH; ColDelta = PixelColAddr & 255; Q21 的 列 号 = (PixelColAddr - ColDelta) >> 8; InterQ21andQ22 = InterTemp[i]; InterQ11andQ12 = ColDelta * (Q12 颜色 – Q11 颜色) + Q11 颜色 * 256; InterTemp[i++] = InterQ11andQ12; 当前行的 InterQ21andQ22 等于上一 行 的 InterQ11andQ12 , 因 此 用 到 InterTemp 辅助数组。。 对于真彩色位图,应该分别对每个像 素的 G、B、R 的值进行处理。 目标像素的值 = (InterQ21andQ22 * 256 + (InterQ11andQ12 - InterQ21andQ22) * RowDelta) >> 16; 对于真彩色位图,应该分别对每个像 素的 G、B、R 的值进行处理。 N 终止
双线性插值图像放大/缩小算法 void ResizeWorkingBitmap(tWorkBMP *a, tWorkBMP *b, WORD bx, WORD by) { unsigned int PtAR = 0, PtBR = 0, PtCR = 0, PtDR = 0, PixelValueR = 0; unsigned int PtAG = 0, PtBG = 0, PtCG = 0, PtDG = 0, PixelValueG = 0; unsigned int PtAB = 0, PtBB = 0, PtCB = 0, PtDB = 0, PixelValueB = 0; register unsigned SpixelColNum = 0, SpixelRowNum = 0, DestCol = 0, DestRow = 0; unsigned int SpixelColAddr = 0, SpixelRowAddr = 0; unsigned int ColDelta = 0, RowDelta = 0, scaleV = 0, scaleH = 0; unsigned int ContribAandBR = 0, ContribCandDR = 0; unsigned int ContribAandBG = 0, ContribCandDG = 0; unsigned int ContribAandBB = 0, ContribCandDB = 0; unsigned int ContribTem[2048 * 3];// Max width is 2048 int i = 0; CreateWorkingBitmap(bx, by, b); // Calculation of zoom proportion scaleH = (a->x << 8) / bx; scaleV = (a->y << 8) / by; // First line of destination image for (DestCol = 0; DestCol < bx; DestCol++) { // Horizontal distance between origin of image and current pixel SpixelColAddr = DestCol * scaleH; // Horizontal distance between A and current pixel ColDelta = SpixelColAddr & 255; // Column number of A SpixelColNum = (SpixelColAddr - ColDelta) >> 8; // Get color of A PtAB = a->b[3 * SpixelRowNum * a->x + 3 * SpixelColNum]; PtAG = a->b[3 * SpixelRowNum * a->x + 3 * SpixelColNum + 1]; PtAR = a->b[3 * SpixelRowNum * a->x + 3 * SpixelColNum + 2]; // Get color of B, C, D if ((SpixelColNum + 1) < a->x) { PtBB = a->b[3 * SpixelRowNum * a->x + 3 * (SpixelColNum + 1)]; PtBG = a->b[3 * SpixelRowNum * a->x + 3 * (SpixelColNum+1) + 1]; PtBR = a->b[3 * SpixelRowNum * a->x + 3 * (SpixelColNum+1) + 2];
PtCB = a->b[3 * (SpixelRowNum+1) * a->x + 3 * SpixelColNum]; PtCG = a->b[3 * (SpixelRowNum+1) * a->x + 3 * SpixelColNum + 1]; PtCR = a->b[3 * (SpixelRowNum+1) * a->x + 3 * SpixelColNum + 2]; PtDB = a->b[3 * (SpixelRowNum + 1) * a->x + 3 * (SpixelColNum + 1)]; PtDG = a->b[3 * (SpixelRowNum+1) * a->x + 3 * (SpixelColNum+1) + 1]; PtDR = a->b[3 * (SpixelRowNum+1) * a->x + 3 * (SpixelColNum+1) + 2]; } else { } PtBB = PtCB = PtDB = PtAB; PtBG = PtCG = PtDG = PtAG; PtBR = PtCR = PtDR = PtAR; // X-direction interpolation of blue ContribAandBB = ColDelta * (PtBB - PtAB) + PtAB * 256; ContribCandDB = ColDelta * (PtDB - PtCB) + PtCB * 256; ContribTem[i++] = ContribCandDB; // Y-direction interpolation of blue PixelValueB = (ContribAandBB * 256 + (ContribCandDB - ContribAandBB) * RowDelta) >> // X-direction interpolation of green ContribAandBG = ColDelta * (PtBG - PtAG) + PtAG * 256; ContribCandDG = ColDelta * (PtDG - PtCG) + PtCG * 256; ContribTem[i++] = ContribCandDG; // Y-direction interpolation of green PixelValueG = (ContribAandBG * 256 + (ContribCandDG - ContribAandBG) * RowDelta) >> // X-direction interpolation of red ContribAandBR = ColDelta * (PtBR - PtAR) + PtAR * 256; ContribCandDR = ColDelta * (PtDR - PtCR) + PtCR * 256; ContribTem[i++] = ContribCandDR; // Y-direction interpolation of red PixelValueR = (ContribAandBR * 256 + (ContribCandDR - ContribAandBR) * RowDelta) >> // Output current pixel to destination image b->b[3 * DestRow * bx + 3 * DestCol] = PixelValueB; b->b[3 * DestRow * bx + 3 * DestCol + 1] = PixelValueG; b->b[3 * DestRow * bx + 3 * DestCol + 2] = PixelValueR; 16; 16; 16; }
分享到:
收藏