精华内容
下载资源
问答
  • HEVC帧间分像素插值

    2021-01-08 17:00:33
    //水平1/2像素插值后的Y做垂直方向1/2像素插值,结果存储在m_filteredBlock[2][2]中 m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width+1, height+1, 2, false, true, chFmt, pattern->...
    Void TEncSearch::xPatternSearchFracDIF(
                                           Bool         bIsLosslessCoded,
                                           TComPattern* pcPatternKey,
                                           Pel*         piRefY,
                                           Int          iRefStride,
                                           TComMv*      pcMvInt,
                                           TComMv&      rcMvHalf,
                                           TComMv&      rcMvQter,
                                           Distortion&  ruiCost
                                          )
    {
      //  Reference pattern initialization (integer scale)
      TComPattern cPatternRoi;
      Int         iOffset    = pcMvInt->getHor() + pcMvInt->getVer() * iRefStride;
      //<piRefY为起始位置,offset为加上运动矢量后,起始位置的偏移
      //<cPatternRoi初始化
      cPatternRoi.initPattern(piRefY + iOffset,
                              pcPatternKey->getROIYWidth(),
                              pcPatternKey->getROIYHeight(),
                              iRefStride,
    #if MCTS_ENC_CHECK
                              pcPatternKey->getBitDepthY(),
                              pcPatternKey->getROIYPosX(),
                              pcPatternKey->getROIYPosY());
    #else
                              pcPatternKey->getBitDepthY());
    #endif
    #if MCTS_ENC_CHECK
      cPatternRoi.setTileBorders(pcPatternKey->getTileLeftTopPelPosX(), pcPatternKey->getTileLeftTopPelPosY(), pcPatternKey->getTileRightBottomPelPosX(), pcPatternKey->getTileRightBottomPelPosY());
    #endif
      //<1/2插值
      //  Half-pel refinement
      xExtDIFUpSamplingH ( &cPatternRoi );
    
      rcMvHalf = *pcMvInt;   rcMvHalf <<= 1;    // for mv-cost
      TComMv baseRefMv(0, 0);
      ruiCost = xPatternRefinement( pcPatternKey, baseRefMv, 2, rcMvHalf, !bIsLosslessCoded );
    
      m_pcRdCost->setCostScale( 0 );
      //<1/4插值
      xExtDIFUpSamplingQ ( &cPatternRoi, rcMvHalf );
      baseRefMv = rcMvHalf;
      baseRefMv <<= 1;
    
      rcMvQter = *pcMvInt;   rcMvQter <<= 1;    // for mv-cost
      rcMvQter += rcMvHalf;  rcMvQter <<= 1;
      ruiCost = xPatternRefinement( pcPatternKey, baseRefMv, 1, rcMvQter, !bIsLosslessCoded );
    }

    1/2插值 

    Void TEncSearch::xExtDIFUpSamplingH( TComPattern* pattern )
    {
      Int width      = pattern->getROIYWidth();
      Int height     = pattern->getROIYHeight();
      Int srcStride  = pattern->getPatternLStride();
    
      Int intStride = m_filteredBlockTmp[0].getStride(COMPONENT_Y);
      Int dstStride = m_filteredBlock[0][0].getStride(COMPONENT_Y);
      Pel *intPtr;
      Pel *dstPtr;
      Int filterSize = NTAPS_LUMA;
      Int halfFilterSize = (filterSize>>1);
      //<参考上下halfFilterSize的像素,垂直偏移(对应filter中src -= ( N/2 - 1 ) * cStride;水平偏移)
      Pel *srcPtr = pattern->getROIY() - halfFilterSize*srcStride - 1;
    
      const ChromaFormat chFmt = m_filteredBlock[0][0].getChromaFormat();
      //<1 将水平整像素存储在m_filteredBlockTmp[0]中
      m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, m_filteredBlockTmp[0].getAddr(COMPONENT_Y), intStride, width+1, height+filterSize, 0, false, chFmt, pattern->getBitDepthY());
      //<2 水平1/2像素插值,结果存储在m_filteredBlockTmp[2]中
      m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, m_filteredBlockTmp[2].getAddr(COMPONENT_Y), intStride, width+1, height+filterSize, 2, false, chFmt, pattern->getBitDepthY());
    
      intPtr = m_filteredBlockTmp[0].getAddr(COMPONENT_Y) + halfFilterSize * intStride + 1;
      dstPtr = m_filteredBlock[0][0].getAddr(COMPONENT_Y);
      //<3 将垂直方向整像素存储在m_filteredBlock[0][0]中
      m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width+0, height+0, 0, false, true, chFmt, pattern->getBitDepthY());
    
      intPtr = m_filteredBlockTmp[0].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride + 1;
      dstPtr = m_filteredBlock[2][0].getAddr(COMPONENT_Y);
      //<4 水平整像素Y做垂直方向1/2像素插值,结果存储在m_filteredBlock[2][0]中
      m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width+0, height+1, 2, false, true, chFmt, pattern->getBitDepthY());
    
      intPtr = m_filteredBlockTmp[2].getAddr(COMPONENT_Y) + halfFilterSize * intStride;
      dstPtr = m_filteredBlock[0][2].getAddr(COMPONENT_Y);
      //<5 水平1/2像素插值的Y结果存储在m_filteredBlock[0][2]中
      m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width+1, height+0, 0, false, true, chFmt, pattern->getBitDepthY());
    
      intPtr = m_filteredBlockTmp[2].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride;
      dstPtr = m_filteredBlock[2][2].getAddr(COMPONENT_Y);
      //<6 水平1/2像素插值后的Y做垂直方向1/2像素插值,结果存储在m_filteredBlock[2][2]中
      m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width+1, height+1, 2, false, true, chFmt, pattern->getBitDepthY());
    }
    

     1/4插值

    Void TEncSearch::xExtDIFUpSamplingQ( TComPattern* pattern, TComMv halfPelRef )
    {
      Int width      = pattern->getROIYWidth();
      Int height     = pattern->getROIYHeight();
      Int srcStride  = pattern->getPatternLStride();
    
      Pel *srcPtr;
      Int intStride = m_filteredBlockTmp[0].getStride(COMPONENT_Y);
      Int dstStride = m_filteredBlock[0][0].getStride(COMPONENT_Y);
      Pel *intPtr;
      Pel *dstPtr;
      Int filterSize = NTAPS_LUMA;
    
      Int halfFilterSize = (filterSize>>1);
    
      Int extHeight = (halfPelRef.getVer() == 0) ? height + filterSize : height + filterSize-1;
    
      const ChromaFormat chFmt = m_filteredBlock[0][0].getChromaFormat();
    
      // Horizontal filter 1/4
      srcPtr = pattern->getROIY() - halfFilterSize * srcStride - 1;
      intPtr = m_filteredBlockTmp[1].getAddr(COMPONENT_Y);
      if (halfPelRef.getVer() > 0)
      {
        srcPtr += srcStride;
      }
      if (halfPelRef.getHor() >= 0)
      {
        srcPtr += 1;
      }
      m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, intPtr, intStride, width, extHeight, 1, false, chFmt, pattern->getBitDepthY());
    
      // Horizontal filter 3/4
      srcPtr = pattern->getROIY() - halfFilterSize*srcStride - 1;
      intPtr = m_filteredBlockTmp[3].getAddr(COMPONENT_Y);
      if (halfPelRef.getVer() > 0)
      {
        srcPtr += srcStride;
      }
      if (halfPelRef.getHor() > 0)
      {
        srcPtr += 1;
      }
      m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, intPtr, intStride, width, extHeight, 3, false, chFmt, pattern->getBitDepthY());
    
      // Generate @ 1,1
      intPtr = m_filteredBlockTmp[1].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride;
      dstPtr = m_filteredBlock[1][1].getAddr(COMPONENT_Y);
      if (halfPelRef.getVer() == 0)
      {
        intPtr += intStride;
      }
      m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 1, false, true, chFmt, pattern->getBitDepthY());
    
      // Generate @ 3,1
      intPtr = m_filteredBlockTmp[1].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride;
      dstPtr = m_filteredBlock[3][1].getAddr(COMPONENT_Y);
      m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 3, false, true, chFmt, pattern->getBitDepthY());
    
      if (halfPelRef.getVer() != 0)
      {
        // Generate @ 2,1
        intPtr = m_filteredBlockTmp[1].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride;
        dstPtr = m_filteredBlock[2][1].getAddr(COMPONENT_Y);
        if (halfPelRef.getVer() == 0)
        {
          intPtr += intStride;
        }
        m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 2, false, true, chFmt, pattern->getBitDepthY());
    
        // Generate @ 2,3
        intPtr = m_filteredBlockTmp[3].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride;
        dstPtr = m_filteredBlock[2][3].getAddr(COMPONENT_Y);
        if (halfPelRef.getVer() == 0)
        {
          intPtr += intStride;
        }
        m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 2, false, true, chFmt, pattern->getBitDepthY());
      }
      else
      {
        // Generate @ 0,1
        intPtr = m_filteredBlockTmp[1].getAddr(COMPONENT_Y) + halfFilterSize * intStride;
        dstPtr = m_filteredBlock[0][1].getAddr(COMPONENT_Y);
        m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 0, false, true, chFmt, pattern->getBitDepthY());
    
        // Generate @ 0,3
        intPtr = m_filteredBlockTmp[3].getAddr(COMPONENT_Y) + halfFilterSize * intStride;
        dstPtr = m_filteredBlock[0][3].getAddr(COMPONENT_Y);
        m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 0, false, true, chFmt, pattern->getBitDepthY());
      }
    
      if (halfPelRef.getHor() != 0)
      {
        // Generate @ 1,2
        intPtr = m_filteredBlockTmp[2].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride;
        dstPtr = m_filteredBlock[1][2].getAddr(COMPONENT_Y);
        if (halfPelRef.getHor() > 0)
        {
          intPtr += 1;
        }
        if (halfPelRef.getVer() >= 0)
        {
          intPtr += intStride;
        }
        m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 1, false, true, chFmt, pattern->getBitDepthY());
    
        // Generate @ 3,2
        intPtr = m_filteredBlockTmp[2].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride;
        dstPtr = m_filteredBlock[3][2].getAddr(COMPONENT_Y);
        if (halfPelRef.getHor() > 0)
        {
          intPtr += 1;
        }
        if (halfPelRef.getVer() > 0)
        {
          intPtr += intStride;
        }
        m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 3, false, true, chFmt, pattern->getBitDepthY());
      }
      else
      {
        // Generate @ 1,0
        intPtr = m_filteredBlockTmp[0].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride + 1;
        dstPtr = m_filteredBlock[1][0].getAddr(COMPONENT_Y);
        if (halfPelRef.getVer() >= 0)
        {
          intPtr += intStride;
        }
        m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 1, false, true, chFmt, pattern->getBitDepthY());
    
        // Generate @ 3,0
        intPtr = m_filteredBlockTmp[0].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride + 1;
        dstPtr = m_filteredBlock[3][0].getAddr(COMPONENT_Y);
        if (halfPelRef.getVer() > 0)
        {
          intPtr += intStride;
        }
        m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 3, false, true, chFmt, pattern->getBitDepthY());
      }
    
      // Generate @ 1,3
      intPtr = m_filteredBlockTmp[3].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride;
      dstPtr = m_filteredBlock[1][3].getAddr(COMPONENT_Y);
      if (halfPelRef.getVer() == 0)
      {
        intPtr += intStride;
      }
      m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 1, false, true, chFmt, pattern->getBitDepthY());
    
      // Generate @ 3,3
      intPtr = m_filteredBlockTmp[3].getAddr(COMPONENT_Y) + (halfFilterSize-1) * intStride;
      dstPtr = m_filteredBlock[3][3].getAddr(COMPONENT_Y);
      m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width, height, 3, false, true, chFmt, pattern->getBitDepthY());
    }

     

    展开全文
  • OpenCV实现像素插值

    2021-12-04 19:22:30
    OpenCV实现像素插值

    进行插值的最基本方法是使用最近邻策略。把待生成图像的像素网格放在原图像的上方,每个新像素被赋予原图像中最邻近像素的值。当图像升采样(即新网格比原始网格更密集时)时,会根据同一个原始像素,确定新网格中多个像素的值。例如要把上面缩小后的图像放大 4 倍,采用最邻近插值法的代码如下所示:

    cv::resize(reduced, newImage, cv::Size(), 3, 3, cv::INTER_NEAREST); 
    
    展开全文
  • 原理 拉格朗日插值法的直观理解和推倒思路,下面知乎这位马同学讲的很好理解 https://www.zhihu.com/question/58333118 这篇博客把整个数学原理,公式推导,讲的很详细了 ...看完这两篇,大致已经知道了拉格朗日插值法...

    原理

    拉格朗日插值法的直观理解和推倒思路,下面知乎这位马同学讲的很好理解
    https://www.zhihu.com/question/58333118
    这篇博客把整个数学原理,公式推导,讲的很详细了
    https://blog.csdn.net/shenwansangz/article/details/88682785

    看完这两篇,大致已经知道了拉格朗日插值法的原理和作用。

    算法推导

    在这里插入图片描述
    在这里插入图片描述
    上面两张图片截取自论文《应用多项式插值函数提高面阵CCD尺寸测量的分辨力_吴晓波》
    其中(Xi,Yj)为通过前面的算法求出的整像素边缘点,(Xe,Ye)则为根据拉格朗日多项式插值法求出的亚像素边缘点坐标。
    图片中的(10)(11)式,就对应拉格朗日插值多项式和拉格朗日基本多项式(插值基函数)
    下面是我关于(12)式的一个自己的推导
    在这里插入图片描述
    (13)式也可以用同样的方法推导出来。

    实现

    实现可以参考这篇博客,写的挺详细
    https://blog.csdn.net/yx123919804/article/details/103123071/
    他参考的论文是下面这篇。
    一种基于多项式插值改进的亚像素细分算法_李庆利.
    此图片来自论文:一种基于多项式插值改进的亚像素细分算法_李庆利
    上面这张图片截取自《一种基于多项式插值改进的亚像素细分算法_李庆利》,可以看到,途中这个红色箭头的函数,其实就是拉格朗日插值多项式,和前一篇论文用的插值法是一样的。

    想说

    上面这些其实就是是我学习这个方法的一整个过程。
    在CSDN上看了很多博客,要么是只有原理,要么就是给一个任何注释也没有的代码,对我这种菜鸟来说,看起来还是蛮吃力的。自己查了许多资料,上面给出链接或者论文名字的都是我自己觉得写的很清楚的,再加上了一点自己的推导过程,整理下来,如果你想了解这个方法,希望我的博客对你有帮助。

    参考

    [1]李庆利,张少军,李忠富,白荫玖,金剑,苟中魁.一种基于多项式插值改进的亚像素细分算法[J].北京科技大学学报,2003(03):280-283.
    [2]吴晓波,钟先信,刘厚权,张启明.应用多项式插值函数提高面阵CCD尺寸测量的分辨力[J].仪器仪表学报,1996(02):154-159.
    拉格朗日插值法理解https://www.zhihu.com/question/58333118
    数学原理+公式推导https://blog.csdn.net/shenwansangz/article/details/88682785
    实现参考https://blog.csdn.net/yx123919804/article/details/103123071/

    展开全文
  • 双三次插值 - 插值图像任意位置亚像素C++ 一、概念 双三次插值又称立方卷积插值。三次卷积插值是一种更加复杂的插值方式。该算法利用待采样点周围16个点的灰度值作三次插值,不仅考虑到4 个直接相邻点的灰度影响,...

    双三次插值 - 插值图像任意位置亚像素C++

    一、概念

    双三次插值又称立方卷积插值。三次卷积插值是一种更加复杂的插值方式。该算法利用待采样点周围16个点的灰度值作三次插值,不仅考虑到4 个直接相邻点的灰度影响,而且考虑到各邻点间灰度值变化率的影响。三次运算可得到更接近高分辨率图像的放大效果,但也导致了运算量的急剧增加。这种算法需要选取插值基函数来拟合数据,其最常用的插值基函数如图1所示,本次实验采用如图所示函数作为基函数。

    图1

    加权算法(a可以不取-0.5):点开链接

    根据比例关系x/X=m/M=1/K,我们可以得到B(X,Y)在A上的对应坐标为A(x,y)=A(X*(m/M),Y*(n/N))=A(X/K,Y/K)。如图所示P点就是目标图像B在(X,Y)处对应于源图像A中的位置,P的坐标位置会出现小数部分,所以我们假设 P的坐标为P(x+u,y+v),其中x,y分别表示整数部分,u,v分别表示小数部分(蓝点到a11方格中红点的距离)。那么我们就可以得到如图所示的最近16个像素的位置,在这里用a(i,j)(i,j=0,1,2,3)来表示,如下图。

    图

    我们要做的就是求出BiCubic函数中的参数x,从而获得上面所说的16个像素所对应的权重W(x)。BiCubic基函数是一维的,而像素是二维的,所以我们将像素点的行与列分开计算。BiCubic函数中的参数x表示该像素点到P点的距离,例如a00距离P(x+u,y+v)的距离为(1+u,1+v),因此a00的横坐标权重i_0=W(1+u),纵坐标权重j_0=W(1+v),a00对B(X,Y)的贡献值为:(a00像素值)* i_0* j_0。因此,a0X的横坐标权重分别为W(1+u),W(u),W(1-u),W(2-u);ay0的纵坐标权重分别为W(1+v),W(v),W(1-v),W(2-v);B(X,Y)像素值为:

    图

    二、代码实现C++(可配合读取图片程序使用)

    #include <iostream>
    #include <tchar.h>
    #include "ImageBuffer.h"
    
    using namespace CamCtrl;
    
    void test()
    {
    	CImageBuffer mCImageBuffer;
    	mCImageBuffer.LoadFromBmp(_T("1.bmp"));
    }
    
    int main()
    {
    	test();
    	return 0;
    }
    
    //功能:双三边插值
    //image:输入图片
    //iImgWidth:图像宽度
    //iImgHeight:图像高度
    //dx,dy:亚像素点与整像素点posy在下x,y上的距离
    //ipos = (posy - 1)*(iImgWidth)+(posx - 1);  //得到ipos
    double CubicPolynomial(unsigned char * image, int iImgWidth, int iImgHeight, double dx, double dy, int ipos)
    {
    	// image为图像各个位置的像素值, iImgWidth为图像的宽度, iImgHeight为图像的高度, ipos为当前插值的位置。
    
    	// 先计算padding 图像的大小。
    	int padding_size = (iImgHeight + 2) * (iImgWidth + 2);
    	double * padding_img = new double[padding_size];
    
    	// 接着对 padding_img 进行赋值。
    	// 将原图像的值赋给padding_img的(2,2)-(iImgHeight+1, iImgWidth+1)
    	// 该部分验证无误。
    	for (int i = 0; i < iImgHeight; i++)
    	{
    		for (int j = 0; j < iImgWidth; j++)
    		{
    			int ipos1 = (i + 1) * (iImgWidth + 2) + (j + 1);
    
    			int temp = i * iImgWidth + j;
    
    			padding_img[ipos1] = image[temp];
    		}
    	}
    
    	// 第一行的值: 第二行、第三行、第四行的值的线性组合.
    	// 该部分验证无误。
    
    	for (int i = 1; i < iImgWidth + 1; i++)
    	{
    		int ipos1 = i;
    
    		double temp1 = padding_img[ipos1 + iImgWidth + 2];
    		double temp2 = padding_img[ipos1 + 2 * (iImgWidth + 2)];
    		double temp3 = padding_img[ipos1 + 3 * (iImgWidth + 2)];
    
    		padding_img[ipos1] = 3 * temp1 - 3 * temp2 + temp3;
    	}
    
    	// 最后一行的值:倒数第二、第三、第四行的值的线性组合。
    	// 该部分验证无误。
    
    	for (int i = 1; i < iImgWidth + 1; i++)
    	{
    		int ipos1 = i + (iImgHeight + 1)*(iImgWidth + 2);
    
    		double temp1 = padding_img[ipos1 - (iImgWidth + 2)];
    		double temp2 = padding_img[ipos1 - 2 * (iImgWidth + 2)];
    		double temp3 = padding_img[ipos1 - 3 * (iImgWidth + 2)];
    
    		padding_img[ipos1] = 3 * temp1 - 3 * temp2 + temp3;
    	}
    
    	// 第一列的值:第二列、第三列、第四列的值的线性组合。
    	// 该部分验证无误。
    	for (int i = 1; i < iImgHeight + 1; i++)
    	{
    		int ipos1 = i * (iImgWidth + 2);
    
    		double temp1 = padding_img[ipos1 + 1];
    		double temp2 = padding_img[ipos1 + 2];
    		double temp3 = padding_img[ipos1 + 3];
    
    		padding_img[ipos1] = 3 * temp1 - 3 * temp2 + temp3;
    	}
    
    	// 最后一列的值:倒数第二、第三、第四列的值的线性组合。
    	// 该部分验证无误。
    	for (int i = 1; i < iImgHeight + 1; i++)
    	{
    		int ipos1 = (i + 1)*(iImgWidth + 2) - 1;
    
    		double temp1 = padding_img[ipos1 - 1];
    		double temp2 = padding_img[ipos1 - 2];
    		double temp3 = padding_img[ipos1 - 3];
    
    		padding_img[ipos1] = 3 * temp1 - 3 * temp2 + temp3;
    	}
    
    	// 后面4个点的组合方向均为列的方向。即ipos+1, ipos+2, ipos+3,或ipos-1, ipos-2, ipos-3.
    
    	// 左上角的点。
    	padding_img[0] = 3 * padding_img[1] - 3 * padding_img[2] + padding_img[3];
    
    	// 右上角的点。
    	padding_img[iImgWidth + 1] = 3 * padding_img[iImgWidth] - 3 * padding_img[iImgWidth - 1] + padding_img[iImgWidth - 2];
    
    	// 左下角的点。
    
    	int pos_left_bottom = (iImgHeight + 1)*(iImgWidth + 2);
    	padding_img[pos_left_bottom] = 3 * padding_img[pos_left_bottom + 1] - 3 * padding_img[pos_left_bottom + 2] + padding_img[pos_left_bottom + 3];
    
    	// 右下角的点。
    
    	int pos_right_bottom = (iImgHeight + 2)*(iImgWidth + 2) - 1;
    	padding_img[pos_right_bottom] = 3 * padding_img[pos_right_bottom - 1] - 3 * padding_img[pos_right_bottom - 2] + padding_img[pos_right_bottom - 3];
    
    
    	// padding结束之后,进行插值操作。首先要把原图的ipos对应到新图的ipos。
    
    	int height = (ipos + 1) / iImgWidth;
    
    	int width = (ipos + 1) - height * iImgWidth;
    
    	// 在新图中的位置。
    
    	int new_ipos = width + (height + 1) * (iImgWidth + 2);
    
    
    	// x方向卷积
    	double dx_2 = dx * dx;
    	double dx_3 = dx * dx*dx;
    	double a4 = (-dx_3 + 2 * dx_2 - dx) / 2;
    	double a5 = (3 * dx_3 - 5 * dx_2 + 2) / 2;
    	double a6 = (-3 * dx_3 + 4 * dx_2 + dx) / 2;
    	double a7 = (dx_3 - dx_2) / 2;
    
    
    
    	double a8 = a4 * padding_img[new_ipos - 1 - (iImgWidth + 2)] + a5 * padding_img[new_ipos - (iImgWidth + 2)] + a6 * padding_img[new_ipos + 1 - (iImgWidth + 2)] + a7 * padding_img[new_ipos + 2 - (iImgWidth + 2)];
    	double a9 = a4 * padding_img[new_ipos - 1] + a5 * padding_img[new_ipos] + a6 * padding_img[new_ipos + 1] + a7 * padding_img[new_ipos + 2];
    	double a10 = a4 * padding_img[new_ipos - 1 + (iImgWidth + 2)] + a5 * padding_img[new_ipos + (iImgWidth + 2)] + a6 * padding_img[new_ipos + 1 + (iImgWidth + 2)] + a7 * padding_img[new_ipos + 2 + (iImgWidth + 2)];
    	double a11 = a4 * padding_img[new_ipos - 1 + 2 * (iImgWidth + 2)] + a5 * padding_img[new_ipos + 2 * (iImgWidth + 2)] + a6 * padding_img[new_ipos + 1 + 2 * (iImgWidth + 2)] + a7 * padding_img[new_ipos + 2 + 2 * (iImgWidth + 2)];
    
    
    
    	// y方向卷积
    	double dy_2 = dy * dy;
    	double dy_3 = dy * dy*dy;
    	double a12 = (-dy_3 + 2 * dy_2 - dy) / 2;
    	double a13 = (3 * dy_3 - 5 * dy_2 + 2) / 2;
    	double a14 = (-3 * dy_3 + 4 * dy_2 + dy) / 2;
    	double a15 = (dy_3 - dy_2) / 2;
    
    	double gray_value;
    	gray_value = a8 * a12 + a9 * a13 + a10 * a14 + a11 * a15;
    
    
    	delete padding_img;
    
    	return gray_value;
    
    
    }
    
    
    

    三、C++代码(基于opencv)

    #include <vector>
    #include "opencv2/core.hpp"
    #include "opencv2/imgproc.hpp"
    #include "opencv2/imgcodecs.hpp"
    #include <opencv2/opencv.hpp>
    #include "bmptools.h"
    #include <cstdlib>
    using namespace std;
    
    using namespace cv;
    
    
    
    double CubicPolynomial(cv::Mat pGray, double dx, double dy, int posx, int posy)
    {	
    	int rows = pGray.rows;
    	int cols = pGray.cols;
    
    	// 创建padding一圈的图像,用来做卷积
    	cv::Mat padded_image = cv::Mat::zeros(rows + 2, cols + 2, CV_64FC1);
    
    	// 将原始图像放置padding图像的中间
    	for (int i = 1; i < padded_image.rows-1; i++)
    	{	
    		for (int j = 1; j < padded_image.cols-1; j++)
    		{
    			double temp = pGray.at<uchar>(i - 1, j - 1);
    			padded_image.at<double>(i, j) = temp;
    		}
    	}
    
    	// 分别计算周围padding一圈的像素值
    	for (int j = 1; j < padded_image.cols-1; j++)
    	{
    		// 第一行
    		padded_image.at<double>(0, j) = 3 * padded_image.at<double>(1, j) - 3 * padded_image.at<double>(2, j) + padded_image.at<double>(3, j);
    		//最后一行
    		padded_image.at<double>(rows + 1, j) = 3 * padded_image.at<double>(rows, j) - 3 * padded_image.at<double>(rows - 1, j) + padded_image.at<double>(rows - 2, j);
    	}
    
    	for (int i = 1; i < padded_image.rows-1; i++)
    	{
    		// 第一列
    		padded_image.at<double>(i, 0) = 3 * padded_image.at<double>(i, 1) - 3 * padded_image.at<double>(i, 2) + padded_image.at<double>(i, 3);
    		// 最后一列
    		padded_image.at<double>(i, cols + 1) = 3 * padded_image.at<double>(i, cols) - 3 * padded_image.at<double>(i, cols - 1) + padded_image.at<double>(i, cols - 2);
    	}
    
    
    	padded_image.at<double>(0, 0) = 3 * padded_image.at<double>(0, 1) - 3 * padded_image.at<double>(0, 2) + padded_image.at<double>(0, 3);
    
    	padded_image.at<double>(0, cols + 1) = 3 * padded_image.at<double>(0, cols) - 3 * padded_image.at<double>(0, cols - 1) + padded_image.at<double>(0, cols - 2);
    
    	padded_image.at<double>(rows + 1, 0) = 3 * padded_image.at<double>(rows + 1, 1) - 3 * padded_image.at<double>(rows + 1, 2) + padded_image.at<double>(rows + 1, 3);
    
    	padded_image.at<double>(rows + 1, cols + 1) = 3 * padded_image.at<double>(rows + 1, cols) - 3 * padded_image.at<double>(rows + 1, cols - 1) + padded_image.at<double>(rows + 1, cols - 2);
    
    	// 卷积的过程
    
    	// x方向卷积
    	double dx_2 = dx*dx;
    	double dx_3 = dx*dx*dx;
    	double a4 = (-dx_3 + 2 * dx_2 - dx) / 2;
    	double a5 = (3 * dx_3 - 5 * dx_2 + 2) / 2;
    	double a6 = (-3 * dx_3 + 4 * dx_2 + dx) / 2;
    	double a7 = (dx_3 - dx_2) / 2;
    
    	double a8 = a4*padded_image.at<double>(posy - 1, posx - 1) + a5*padded_image.at<double>(posy - 1, posx) + a6*padded_image.at<double>(posy - 1, posx + 1) + a7*padded_image.at<double>(posy - 1, posx + 2);
    	double a9 = a4*padded_image.at<double>(posy, posx - 1) + a5*padded_image.at<double>(posy, posx) + a6*padded_image.at<double>(posy, posx + 1) + a7*padded_image.at<double>(posy, posx + 2);
    	double a10 = a4*padded_image.at<double>(posy + 1, posx - 1) + a5*padded_image.at<double>(posy + 1, posx) + a6*padded_image.at<double>(posy + 1, posx + 1) + a7*padded_image.at<double>(posy + 1, posx + 2);
    	double a11 = a4*padded_image.at<double>(posy + 2, posx - 1) + a5*padded_image.at<double>(posy + 2, posx) + a6*padded_image.at<double>(posy + 2, posx + 1) + a7*padded_image.at<double>(posy + 2, posx + 2);
    
    	// y方向卷积
    	double dy_2 = dy*dy;
    	double dy_3 = dy*dy*dy;
    	double a12 = (-dy_3 + 2 * dy_2 - dy) / 2;
    	double a13 = (3 * dy_3 - 5 * dy_2 + 2) / 2;
    	double a14 = (-3 * dy_3 + 4 * dy_2 + dy) / 2;
    	double a15 = (dy_3 - dy_2) / 2;
    
    	double gray_value;
    	gray_value = a8*a12 + a9*a13 + a10*a14 + a11*a15;
    
    	return gray_value;
    }
    
    
    // 这里的ipos是原图像中的位置,要把它对应到padding后图像的ipos,才能进行插值计算。
    
    double CubicPolynomial(unsigned char * image, int iImgWidth, int iImgHeight, double dx, double dy, int ipos)
    {
    	// image为图像各个位置的像素值, iImgWidth为图像的宽度, iImgHeight为图像的高度, ipos为当前插值的位置。
    
    	// 先计算padding 图像的大小。
    	int padding_size = (iImgHeight + 2) * (iImgWidth + 2);
    	double * padding_img = new double[padding_size];
    
    	// 接着对 padding_img 进行赋值。
    	// 将原图像的值赋给padding_img的(2,2)-(iImgHeight+1, iImgWidth+1)
    	// 该部分验证无误。
    	for (int i = 0; i < iImgHeight; i++)
    	{
    		for (int j = 0; j < iImgWidth; j++)
    		{
    			int ipos1 = (i+1) * (iImgWidth+2) + (j+1);
    
    			int temp = i*iImgWidth + j;
    
    			padding_img[ipos1] = image[temp];
    		}
    	}
    
    
    	// 第一行的值: 第二行、第三行、第四行的值的线性组合.
    	// 该部分验证无误。
    
    	for (int i = 1; i < iImgWidth+1; i++)
    	{
    		int ipos1 = i;
    
    		double temp1 = padding_img[ipos1 + iImgWidth + 2];
    		double temp2 = padding_img[ipos1 + 2 * (iImgWidth + 2)];
    		double temp3 = padding_img[ipos1 + 3 * (iImgWidth + 2)];
    
    		padding_img[ipos1] = 3 * temp1 - 3 * temp2 + temp3;
    	}
    
    
    	// 最后一行的值:倒数第二、第三、第四行的值的线性组合。
    	// 该部分验证无误。
    
    	for (int i = 1; i < iImgWidth+1; i++)
    	{
    		int ipos1 = i + (iImgHeight + 1)*(iImgWidth + 2);
    
    		double temp1 = padding_img[ipos1 - (iImgWidth + 2)];
    		double temp2 = padding_img[ipos1 - 2 * (iImgWidth + 2)];
    		double temp3 = padding_img[ipos1 - 3 * (iImgWidth + 2)];
    
    		padding_img[ipos1] = 3 * temp1 - 3 * temp2 + temp3;
    	}
    
    	// 第一列的值:第二列、第三列、第四列的值的线性组合。
    	// 该部分验证无误。
    	for (int i = 1; i < iImgHeight+1; i++)
    	{
    		int ipos1 = i * (iImgWidth + 2);
    		
    		double temp1 = padding_img[ipos1 + 1];
    		double temp2 = padding_img[ipos1 + 2];
    		double temp3 = padding_img[ipos1 + 3];
    
    		padding_img[ipos1] = 3 * temp1 - 3 * temp2 + temp3;
    	}
    
    	// 最后一列的值:倒数第二、第三、第四列的值的线性组合。
    	// 该部分验证无误。
    	for (int i = 1; i < iImgHeight+1; i++)
    	{
    		int ipos1 = (i + 1)*(iImgWidth + 2) - 1;
    
    		double temp1 = padding_img[ipos1 - 1];
    		double temp2 = padding_img[ipos1 - 2];
    		double temp3 = padding_img[ipos1 - 3];
    
    		padding_img[ipos1] = 3 * temp1 - 3 * temp2 + temp3;
    	}
    
    	// 后面4个点的组合方向均为列的方向。即ipos+1, ipos+2, ipos+3,或ipos-1, ipos-2, ipos-3.
    
    	// 左上角的点。
    	padding_img[0] = 3 * padding_img[1] - 3 * padding_img[2] + padding_img[3];
    
    	// 右上角的点。
    	padding_img[iImgWidth + 1] = 3 * padding_img[iImgWidth] - 3 * padding_img[iImgWidth - 1] + padding_img[iImgWidth - 2];
    
    	// 左下角的点。
    
    	int pos_left_bottom = (iImgHeight + 1)*(iImgWidth + 2);
    	padding_img[pos_left_bottom] = 3 * padding_img[pos_left_bottom + 1] - 3 * padding_img[pos_left_bottom + 2] + padding_img[pos_left_bottom + 3];
    
    	// 右下角的点。
    
    	int pos_right_bottom = (iImgHeight + 2)*(iImgWidth + 2) - 1;
    	padding_img[pos_right_bottom] = 3 * padding_img[pos_right_bottom - 1] - 3 * padding_img[pos_right_bottom - 2] + padding_img[pos_right_bottom - 3];
    
    	
    	// padding结束之后,进行插值操作。首先要把原图的ipos对应到新图的ipos。
    
    	int height = (ipos + 1) / iImgWidth;
    
    	int width = (ipos + 1) - height*iImgWidth;
    
    	// 在新图中的位置。
    
    	int new_ipos = width + (height+1) * (iImgWidth + 2);
    
    
    	// x方向卷积
    	double dx_2 = dx*dx;
    	double dx_3 = dx*dx*dx;
    	double a4 = (-dx_3 + 2 * dx_2 - dx) / 2;
    	double a5 = (3 * dx_3 - 5 * dx_2 + 2) / 2;
    	double a6 = (-3 * dx_3 + 4 * dx_2 + dx) / 2;
    	double a7 = (dx_3 - dx_2) / 2;
    
    
    
    	double a8 = a4*padding_img[new_ipos - 1 - (iImgWidth + 2)] + a5*padding_img[new_ipos - (iImgWidth + 2)] + a6 * padding_img[new_ipos + 1 - (iImgWidth + 2)] + a7 * padding_img[new_ipos + 2 - (iImgWidth + 2)];
    	double a9 = a4*padding_img[new_ipos - 1] + a5*padding_img[new_ipos] + a6 * padding_img[new_ipos + 1] + a7 * padding_img[new_ipos + 2];
    	double a10 = a4*padding_img[new_ipos - 1 + (iImgWidth + 2)] + a5*padding_img[new_ipos + (iImgWidth + 2)] + a6 * padding_img[new_ipos + 1 + (iImgWidth + 2)] + a7 * padding_img[new_ipos + 2 + (iImgWidth + 2)];
    	double a11 = a4*padding_img[new_ipos - 1 + 2 * (iImgWidth + 2)] + a5*padding_img[new_ipos + 2 * (iImgWidth + 2)] + a6 * padding_img[new_ipos + 1 + 2 * (iImgWidth + 2)] + a7 * padding_img[new_ipos + 2 + 2 * (iImgWidth + 2)];
    	
    
    
    	// y方向卷积
    	double dy_2 = dy*dy;
    	double dy_3 = dy*dy*dy;
    	double a12 = (-dy_3 + 2 * dy_2 - dy) / 2;
    	double a13 = (3 * dy_3 - 5 * dy_2 + 2) / 2;
    	double a14 = (-3 * dy_3 + 4 * dy_2 + dy) / 2;
    	double a15 = (dy_3 - dy_2) / 2;
    
    	double gray_value;
    	gray_value = a8*a12 + a9*a13 + a10*a14 + a11*a15;
    
    	return gray_value;
    
    
    }
    
    
    int main(int argc, char **argv)
    {
    
    	// imageData为图像数据,unsigned char * 型
    
    	Mat image = imread("F:\\img\\image\\result1.jpg", 0);
    	int image_size = image.cols * image.rows;
    	unsigned char* imageData = new unsigned char[image_size];
    
    	int a = 0;
    	for (int i = 0; i<image.rows; i++)
    	{
    		for (int j = 0; j<image.cols; j++)
    		{
    			imageData[a] = image.at<uchar>(i, j);
    			a++;
    		}
    	}
    
    
    
    	int iImgHeight = image.rows;
    	int iImgWidth = image.cols;
    
    	// 进行多次随机试验。
    
    	for (int i = 0; i < 1000; i++)
    	{
    
    		// x是列方向,y是行方向,在cv::Mat做输入的函数中,起始点为(1,1)点。
    
    
    
    		// 生成随机位置。
    		int x = rand() % (iImgWidth - 1) + 1;
    		int y = rand() % (iImgHeight - 1) + 1;
    
    		// 对应回原图像下的ipos。
    		int ipos = (y - 1)*(iImgWidth)+(x - 1);
    
    
    		// 生成随机的dx, dy.
    		int N = 10000;
    		double dx = rand() % (N + 1) / (float)(N + 1);;
    		double dy = rand() % (N + 1) / (float)(N + 1);;
    
    
    		// 基于unsigned char * 数据的插值结果。
    		double temp1 = CubicPolynomial(imageData, iImgWidth, iImgHeight, dx, dy, ipos);
    
    		// 基于cv::Mat 数据的插值结果。
    		double temp2 = CubicPolynomial(image, dx, dy, x, y);
    
    		double difference = abs(temp2 - temp1);
    
    		cout << "The difference is : " << difference << endl;
    
    
    	}
    
    
    	system("pause");
    	return 0;
    }
    

    四、Matlab代码

    function Value = CubicInterpoly(y,x,img)
        uw = floor(x);
        vw = floor(y);
        pV = zeros(16,1);
        W = zeros(16,2);
        
        pV(1) = img(vw-1,uw-1);
        W(1,:) = BiCubic(y,x,vw-1,uw-1);
        pV(2) = img(vw-1,uw);
        W(2,:) = BiCubic(y,x,vw-1,uw);
        pV(3) = img(vw-1,uw+1);
        W(3,:) = BiCubic(y,x,vw-1,uw+1);
        pV(4) = img(vw-1,uw+2);
        W(4,:) = BiCubic(y,x,vw-1,uw+2);
    
        pV(5) = img(vw,uw-1);
        W(5,:) = BiCubic(y,x,vw,uw-1);
        pV(6) = img(vw,uw);
        W(6,:) = BiCubic(y,x,vw,uw);
        pV(7) = img(vw,uw+1);
        W(7,:) = BiCubic(y,x,vw,uw+1);
        pV(8) = img(vw,uw+2);
        W(8,:) = BiCubic(y,x,vw,uw+2);
        
        pV(9) = img(vw+1,uw-1);
        W(9,:) = BiCubic(y,x,vw+1,uw-1);
        pV(10) = img(vw+1,uw);
        W(10,:) = BiCubic(y,x,vw+1,uw);
        pV(11) = img(vw+1,uw+1);
        W(11,:) = BiCubic(y,x,vw+1,uw+1);
        pV(12) = img(vw+1,uw+2);
        W(12,:) = BiCubic(y,x,vw+1,uw+2);
        
        pV(13) = img(vw+2,uw-1);
        W(13,:) = BiCubic(y,x,vw+2,uw-1);
        pV(14) = img(vw+2,uw);
        W(14,:) = BiCubic(y,x,vw+2,uw);
        pV(15) = img(vw+2,uw+1);
        W(15,:) = BiCubic(y,x,vw+2,uw+1);
        pV(16) = img(vw+2,uw+2);
        W(16,:) = BiCubic(y,x,vw+2,uw+2);
        
        Value = 0;
        for i=1:16
            Value = Value + pV(i)*W(i,1)*W(i,2);
        end
    end
    
    function W = BiCubic(y,x,yi,xi)
        W = zeros(1,2);
        a = -0.5;
        distX = abs(x-xi);
        if(distX <=1)
            W(1) = (a+2)*distX^3-(a+3)*distX^2+1;
        elseif(distX > 1 && distX <2)
            W(1) = a*distX^3-5*a*distX^2+8*a*distX-4*a;
        else
            W(1) = 0;
        end
        distY = abs(y-yi);
        if(distY <=1)
            W(2) = (a+2)*distY^3-(a+3)*distY^2+1;
        elseif(distY > 1 && distY <2)
            W(2) = a*distY^3-5*a*distY^2+8*a*distY-4*a;
        else
            W(2) = 0;
        end
    end
    
    展开全文
  • 传统的边缘检测方法的检测精度最高只能达到一个像素级,但是,随着科学技术的飞速发展,工业检测等应用对精确度的要求不断提高,传统的像素级边缘检测方法已经不能满足实际测量的需要,本文重点介绍的亚像素边缘检测...
  • == 225: if pAmp2[c] > pAmp1[c + 1] and pAmp2[c] >= pAmp3[c - 1]: pEdge[c] = 255 """ 显示单像素图像 """ # edge = cv2.convertScaleAbs(edge) # cv2.imshow('edge',edge) # cv2.imwrite('edge.png', edge) # ...
  • 调整图像大小的三种插值算法总结

    千次阅读 2021-06-11 09:21:02
    我们简单地将最近的像素插值到当前像素。假设,我们从0开始索引像素的值。下面2x2图像的像素如下:{’ 10 ‘:(0,0),’ 20 ‘:(1,0),’ 30 ‘:(0,1),’ 40 ':(1,1)} 然后我们将此图像投射到4x4图像上,我们需要...
  • 1.学习目标 最近邻插值算法 双线性插值算法 掌握OpenCV框架下插值...  在讲双线性插值之前先看以一下线性插值,线性插值多项式为:f(x)=ax+b   双线性插值就是线性插值在二维时的推广,在两个方向.
  • opencv 亚像素 算法

    2020-12-22 12:41:59
    像素算法亚像素算法的基本思路就是将一个像素再分为更小的单位。也就是说1个像素的灰度值分为256级。所以,以这类系统为例,进行亚像素计算就要把像素分为255个小单位。或许,可以这样来理解“亚像素算法”。一个...
  • 插值算法 图像常用的插值算法有两种,一种是最近邻插值算法,另外一种是双线性插值算法。最近邻插值算法,顾名思义最近邻插值,是指将目标图像中的点,对应到源图像中后,找到最相邻的整数点,作为插值后的输出。 ...
  • 像素精准边缘定位

    2021-04-21 09:02:25
    1.http://download.csdn.net/detail/pkma75/925394pkma75资源积分:1分备注:pdf格式,用曲线拟合的方法计算亚像素,编程易实现,具有较强的实用...kuailechengzi资源积分:1分备注:亚像素边缘检测方法,此种方法先...
  • 原文链接:图像bayer格式介绍以及bayer插值原理CFA_1lang-CSDN博客 核心算法的MATLAB代码如下 I = (ORIGINAL_BAYER_IMAGE) %此处用于替换任何已经通过imread加载的可被读取的单通道BAYER格式CFA-IMAGE %I = A ...
  • 【Halcon视觉】图像亚像素边缘提取

    千次阅读 2021-08-25 18:29:36
    像素边缘提取原理:采用插值算法,精确定位边缘的位置。 Halcon提供了亚像素边缘提取方法,可直接获取高精度的亚像素边缘。 算子:edges_sub_pix () 亚像素边缘 *关闭窗口 dev_close_window () *打开...
  • [设已知单位正方形的四个顶点坐标分别为:f(0,0),f(1,0),f(1,0),f(1,1)f(0,0),f(1, 0),f(1,0), f(1,1),通过双线性插值的方式得到正方形内任意点 f(x,y)f(x,y) 的值。(1双线性插值实现图像放大一、算法伪代码 二、...
  • 用法同 openCV,使用最小二乘迭代function corners_tuned = refine_pos( src, corners) % corners: N*2%UNTITLED Summary of this function goes here% Detailed explanation goes herecorners_tuned = corners;...
  • 帧间预测是利用图像帧与图像帧之间的相关性,也就是 视频时间域的相关性,通过已编码像素预测当前块的像素,有助于去除视频时域冗余,大大压缩数据。帧间预测编码比帧内预测编码压缩比要大得多。 帧间预测主要的工作...
  • 帧间预测是利用视频时域的相关性,使用邻近已编码图像像素预测当前图像的像素,以达到有效去除视频时域冗余的目的。由于视频序列通常包括较强的时域相关性,因此预测残差通常是“平坦的”,即很多残差值接近于“0”...
  • 1.插值和滤波(version20100611) 1.1.程序运行设置 在插值和滤波,程序运行的设置为。 表格‑:插值和滤波,程序运行设置 参数 ... SATD判决模式,1/4像素 --thread 1 ..
  • 插值算法:最近邻插值、双线性插值 插值算法有很多种,这里列出关联比较密切的三种: 最近邻法(Nearest Interpolation):计算速度最快,但是效果最差。 双线性插值(Bilinear Interpolation):双线性插值是用原图像...
  • 9月4日,荣耀在武汉发布了“秘密...而@荣耀老熊则在微博上特别提到了“相比一些靠1200万像素插值成4800万的误导宣传,荣耀Play3的4800万硬件直出更真材实料。4800万像素硬件直出和插值区别非常大,欢迎对比PK”,那...
  • 最近邻插值与双线性插值

    千次阅读 2021-11-14 15:02:20
    顾名思义,最近邻插值法在放大图像时补充的像素是最近邻的像素的值。由于方法简单,所以处理速度很快,但是得到的图像常常含有锯齿边缘。如下图所示: import cv2 import numpy as np def function(img): height,...
  • 在图像处理中,如果需要对图像进行缩放,一般可以采取插值法,最常用的就是双线性插值法。本文首先从数学角度推导了一维线性插值和二维线性插值的计算过程,并总结了规律。随后将其应用到图像的双线性插值上,利用...
  • 最近邻插值是最简单的一种插值方法,不需要计算,在待求象素的四邻像素中,将距离待求象素最近的邻像素灰度赋给待求像素。设i+u, j+v (i, j为正整数, u, v为大于零小于1的小数,下同)为待求象素坐标,则待求象素...
  • 在介绍双线性插值之前,先讲一下线性插值:已知数据(x0,y0),要计算[x0,x1]区间内某一位置x在直线上的y值:上面这个比较好理解,仔细看就是用x和x0,x1的距离作为一个权重,用于y0和y1的加权。双线性插值本质就是在...
  • OpenGL插值

    2021-03-20 10:54:56
    OpenGL插值OpenGL插值简介源代码剖析主要源代码 OpenGL插值简介 本课演示了 3D 管道的一个重要部分 – 通过变量从顶点着色器输出的插值。如前所述,要在屏幕上获取任何对象,必须将顶点着色器的一个变量命名为"gl_...
  • 详解Python实现线性插值

    千次阅读 2021-01-14 07:46:34
    在算法分析过程中,我们经常会遇到数据需要处理插值的过程,为了方便理解,我们这里给出相关概念和源程序,希望能帮助到您!案例一:已知坐标 (x0, y0) 与 (x1, y1),要求得区间 [x0, x1] 内某一点位置 x 在直线上的y...
  • c语言插值算法

    2021-05-19 08:09:46
    1、插值算法,讲座人:邓书莉 时间: 2010年12月9日 编写排版:邓书莉,插值算法,插值的定义 一维插值算法 最邻近插值 线性插值 拉格朗日插值 牛顿插值 埃尔米特插值 三次样条插值,二维插值算法 最邻近插值 双线性插值...
  • MATLAB实现拉格朗日插值

    千次阅读 2021-01-17 12:40:32
    开始学习MATLAB(R和Python先放一放。。。),老师推荐一本书,看完基础就是各种算法。。。首先是各种插值。...%lagran1.m%求拉格朗日插值多项式和基函数%输入的量:n+1个节点(x_i,y_i)(i = 1,2, ... , n...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 36,998
精华内容 14,799
关键字:

像素插值