十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

【matlab】代码库-双线性插值(与RTL对齐)

【matlab】代码库-双线性插值(与RTL对齐) 线性插值函数1 线性插值1.1 单次调用1.2 循环调用加速Img RGB共用一个LUT1.3 循环调用加速Img RGB分别一个LUT2 双线性插值2.1 单次调用2.2 循环调用加速Img RGB共用一个LUT2.3 循环调用加速Img RGB分别一个LUT1 线性插值1.1 单次调用interp_1D函数一维线性插值摘要该MATLAB函数interp_1D实现一维线性插值功能。首先检查输入点数组和值数组的维度一致性并统一转换为列向量。通过遍历查找给定点是否与查找表(LUT)中的点匹配若未找到则进行线性插值计算确定相邻上下界点按比例计算插值结果。还处理了超出LUT范围的情况直接返回边界值。函数支持非均匀间隔的输入点并包含零斜率情况的特殊处理。functionoutlinear_RTL(query,nodes,lut)% linear - 一维线性插值查表RTL行为对齐分步向0取整%% 调用方法% out linear(query, nodes, lut)%% 输入参数% query - 待插值的查询点标量 或 向量支持行向量/列向量% nodes - LUT的横坐标节点向量必须严格单调递增或递减% lut - LUT对应的纵坐标值向量与nodes同长度%% 输出参数% out - 插值结果维度与 query 相同整数每一步向0取整isRowVector(size(query,1)1);queryquery(:);nodesnodes(:);lutlut(:);iflength(nodes)~length(lut)error(nodes 和 lut 长度必须一致);enddiffNodesdiff(nodes);ifall(diffNodes0)isIncreasingtrue;elseifall(diffNodes0)isIncreasingfalse;elseerror(nodes 必须严格单调递增或递减);endif~isIncreasing nodesflipud(nodes);lutflipud(lut);endnumPointslength(query);outzeros(numPoints,1);fori1:numPoints pquery(i);% ---- 边界检查 ----ifpnodes(1)warning(query(%.4f) 超出或等于LUT下限使用最小边界值,p);out(i)fix(lut(1));continue;endifpnodes(end)warning(query(%.4f) 超出或等于LUT上限使用最大边界值,p);out(i)fix(lut(end));continue;end% ---- 查找 p 落在哪两个 nodes 之间 ----idxfind(nodesp,1,first);% 如果 p 恰好等于某个节点值find 会返回该节点索引% 此时需要将 idx 减 1取该节点和上一个节点if~isempty(idx)nodes(idx)pifidx1out(i)fix(lut(1));continue;elseidxidx-1;endelseifisempty(idx)out(i)fix(lut(end));continue;elseifidx1out(i)fix(lut(1));continue;endx1nodes(idx);x2nodes(idx1);y1lut(idx);y2lut(idx1);dxfix(p-x1);dyfix(y2-y1);step_xfix(x2-x1);temp1fix(dy*dx);temp2fix(temp1/step_x);out(i)fix(y1temp2);endifisRowVector outout;endend1.2 循环调用加速Img RGB共用一个LUT暂无1.3 循环调用加速Img RGB分别一个LUT暂无2 双线性插值2.1 单次调用interp_2D函数实现双线性插值摘要该MATLAB函数interp_2D实现了二维双线性插值算法。函数接受两个点的坐标及其对应的查找表点通过fund_updowm辅助函数确定相邻点位置后先在x方向进行线性插值生成中间值再在y方向进行插值计算最终结果。算法能正确处理边界情况当点位于查找表节点时直接取值适用于二维网格数据的插值计算。functionoutbilinear_RTL(query_x,query_y,nodes_x,nodes_y,lut)% bilinear - 二维双线性插值查表RTL行为对齐分步向0取整%% 调用方法% out bilinear(query_x, query_y, nodes_x, nodes_y, lut)%% 输入参数% query_x - 待插值的x方向查询点标量 或 向量% query_y - 待插值的y方向查询点标量 或 向量% nodes_x - LUT的x方向坐标节点向量必须严格单调递增或递减% nodes_y - LUT的y方向坐标节点向量必须严格单调递增或递减% lut - 二维LUT表矩阵大小为 [length(nodes_y), length(nodes_x)]% 行对应 nodes_y列对应 nodes_x%% 输出参数% out - 插值结果维度与 query_x/query_y 相同query_xquery_x(:);query_yquery_y(:);iflength(query_x)~length(query_y)error(query_x 和 query_y 长度必须一致);endisRowVector(size(query_x,1)1);nodes_xnodes_x(:);nodes_ynodes_y(:);diffNodesXdiff(nodes_x);ifall(diffNodesX0)isXIncreasingtrue;elseifall(diffNodesX0)isXIncreasingfalse;elseerror(nodes_x 必须严格单调递增或递减);enddiffNodesYdiff(nodes_y);ifall(diffNodesY0)isYIncreasingtrue;elseifall(diffNodesY0)isYIncreasingfalse;elseerror(nodes_y 必须严格单调递增或递减);endif~isXIncreasing nodes_xflipud(nodes_x);lutfliplr(lut);endif~isYIncreasing nodes_yflipud(nodes_y);lutflipud(lut);endifsize(lut,1)~length(nodes_y)||size(lut,2)~length(nodes_x)error(LUT维度与 nodes_x/nodes_y 不匹配);endnumPointslength(query_x);outzeros(numPoints,1);fori1:numPoints pxquery_x(i);pyquery_y(i);% ---- x方向查找 ----ifpxnodes_x(1)idx_x1;x1nodes_x(1);x2nodes_x(2);x_boundarytrue;elseifpxnodes_x(end)idx_xlength(nodes_x)-1;x1nodes_x(end-1);x2nodes_x(end);x_boundarytrue;else% 查找第一个大于 px 的索引idx_xfind(nodes_xpx,1,first);% 如果 px 恰好等于某个节点值find 会返回该节点索引% 此时需要将 idx_x 减 1取该节点和上一个节点if~isempty(idx_x)nodes_x(idx_x)pxifidx_x1idx_x1;x1nodes_x(1);x2nodes_x(2);elseidx_xidx_x-1;x1nodes_x(idx_x);x2nodes_x(idx_x1);endelseifisempty(idx_x)out(i)fix(lut(end,end));continue;elseifidx_x1idx_x1;x1nodes_x(1);x2nodes_x(2);elsex1nodes_x(idx_x-1);x2nodes_x(idx_x);idx_xidx_x-1;endx_boundaryfalse;end% ---- y方向查找 ----ifpynodes_y(1)idx_y1;y1nodes_y(1);y2nodes_y(2);y_boundarytrue;elseifpynodes_y(end)idx_ylength(nodes_y)-1;y1nodes_y(end-1);y2nodes_y(end);y_boundarytrue;elseidx_yfind(nodes_ypy,1,first);if~isempty(idx_y)nodes_y(idx_y)pyifidx_y1idx_y1;y1nodes_y(1);y2nodes_y(2);elseidx_yidx_y-1;y1nodes_y(idx_y);y2nodes_y(idx_y1);endelseifisempty(idx_y)out(i)fix(lut(end,end));continue;elseifidx_y1idx_y1;y1nodes_y(1);y2nodes_y(2);elsey1nodes_y(idx_y-1);y2nodes_y(idx_y);idx_yidx_y-1;endy_boundaryfalse;end% ---- 获取四个角点 ----Q11lut(idx_y,idx_x);Q12lut(idx_y1,idx_x);Q21lut(idx_y,idx_x1);Q22lut(idx_y1,idx_x1);ifx_boundaryy_boundaryout(i)fix(Q11);continue;end% ---- 计算距离权重 ----dx1fix(px-x1);dx2fix(x2-px);dy1fix(py-y1);dy2fix(y2-py);step_xfix(x2-x1);step_yfix(y2-y1);% ---- 双线性插值 ----term1fix(fix(dx2*dy2)*Q11);term2fix(fix(dx1*dy2)*Q21);term3fix(fix(dx2*dy1)*Q12);term4fix(fix(dx1*dy1)*Q22);numeratorfix(term1term2term3term4);denominatorfix(step_x*step_y);ifdenominator0out(i)fix(Q11);elseout(i)fix(numerator/denominator);end% ---- 边界单方向插值 ----ifx_boundary~y_boundary temp_numfix(fix(dy2*Q11)fix(dy1*Q12));out(i)fix(temp_num/step_y);elseif~x_boundaryy_boundary temp_numfix(fix(dx2*Q11)fix(dx1*Q21));out(i)fix(temp_num/step_x);endendifisRowVector outout;endend2.2 循环调用加速Img RGB共用一个LUT请注意Lut方向functionoutImgbilinearForImg(query_x_img,query_y_fixed,nodes_x,nodes_y,lut)% bilinearForImg - 图像双线性插值查表固定DBV整图加速版%% 调用方法% outImg bilinearForImg(query_x_img, query_y_fixed, nodes_x, nodes_y, lut)%% 输入参数% query_x_img - 输入图像灰度图或RGB三通道对应 nodes_x行方向% query_y_fixed - 固定的 DBV 值标量对应 nodes_y列方向% nodes_x - LUT的行方向坐标节点% nodes_y - LUT的列方向坐标节点% lut - 二维LUT表size [length(nodes_x), length(nodes_y)]%% 输出参数% outImg - 输出图像大小与输入相同nodes_xnodes_x(:);nodes_ynodes_y(:);ifany(diff(nodes_x)0)||any(diff(nodes_y)0)error(nodes_x 和 nodes_y 必须严格单调递增);end[H,W,C]size(query_x_img);img_doubledouble(query_x_img);% ---- 固定 query_y_fixed 对应的 y 方向索引 ----% query_y_fixed → nodes_y列方向ifquery_y_fixednodes_y(1)idx_y1;y1nodes_y(1);y2nodes_y(2);elseifquery_y_fixednodes_y(end)idx_ylength(nodes_y)-1;y1nodes_y(end-1);y2nodes_y(end);elseidx_yfind(nodes_yquery_y_fixed,1,first);if~isempty(idx_y)nodes_y(idx_y)query_y_fixedifidx_y1idx_y1;y1nodes_y(1);y2nodes_y(2);elseidx_yidx_y-1;y1nodes_y(idx_y);y2nodes_y(idx_y1);endelseifisempty(idx_y)error(query_y_fixed 超出节点范围);elseifidx_y1idx_y1;y1nodes_y(1);y2nodes_y(2);elsey1nodes_y(idx_y-1);y2nodes_y(idx_y);idx_yidx_y-1;endend% 预计算 y 方向权重所有像素共用dy1fix(query_y_fixed-y1);dy2fix(y2-query_y_fixed);step_yfix(y2-y1);% ---- 对图像每个像素进行 x 方向插值 ----% query_x_img → nodes_x行方向img_flatimg_double(:);numPixelslength(img_flat);idx_xdiscretize(img_flat,nodes_x);idx_x(img_flatnodes_x(1))1;idx_x(img_flatnodes_x(end))length(nodes_x)-1;idx_x(isnan(idx_x))1;x1nodes_x(idx_x);x2nodes_x(idx_x1);dx1fix(img_flat-x1);dx2fix(x2-img_flat);step_xfix(x2-x1);% ---- 获取四个角点值 ----idx_y_vecidx_y*ones(numPixels,1);idx_y1_vec(idx_y1)*ones(numPixels,1);idx_Q11sub2ind(size(lut),idx_x,idx_y_vec);idx_Q12sub2ind(size(lut),idx_x,idx_y1_vec);idx_Q21sub2ind(size(lut),idx_x1,idx_y_vec);idx_Q22sub2ind(size(lut),idx_x1,idx_y1_vec);Q11lut(idx_Q11);Q12lut(idx_Q12);Q21lut(idx_Q21);Q22lut(idx_Q22);% ---- 双线性插值与 bilinear_RTL 完全一致 ----% term1 dx2 * dy2 * Q11% term2 dx1 * dy2 * Q21% term3 dx2 * dy1 * Q12% term4 dx1 * dy1 * Q22term1fix(fix(dx2.*dy2).*Q11);term2fix(fix(dx1.*dy2).*Q21);term3fix(fix(dx2.*dy1).*Q12);term4fix(fix(dx1.*dy1).*Q22);numeratorfix(term1term2term3term4);denominatorfix(step_x.*step_y);denominator(denominator0)1;out_flatfix(numerator./denominator);% ---- 恢复图像形状 ----outImgreshape(out_flat,[H,W,C]);ifisa(query_x_img,uint8)outImguint8(outImg);elseifisa(query_x_img,uint16)outImguint16(outImg);elseifisa(query_x_img,int16)outImgint16(outImg);endend2.3 循环调用加速Img RGB分别一个LUT暂无
返回列表