欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

纯C++超分辨率重建SRCNN --改编--(五)卷积边界填充

程序员文章站 2023-12-30 19:24:46
...

前面的重建图边界有个方框,影响效果,这里改进一下,加上边界填充。

1。‘replicate’ 图像大小通过复制外边界的值来扩展

 2。'same'切去一部分,让输出与输入图像的大小相同

卷积实现上面的两个参数:

void 卷积(卷积矩阵*filter,卷积矩阵*arr, 卷积矩阵*res)
{
	int filterW=filter->width;
	int filterH=filter->height;
	int arrW=arr->width;
	int arrH=arr->height;

    float temp;  
	int tmpW=filterW*2+arrW;//扩展输入宽   + 2 个核宽
	int tmpH=filterH*2+arrH;//扩展输入高

	卷积矩阵  tmp(tmpW,tmpH);
	
	//边宽高(单)
	int w2=filterW;
	int h2=filterH;

	int i,j,m,n;

	//复制输入
	for (i=0; i<arrH; i++)  //输入
    {  
        for (j=0; j<arrW; j++)  
        {  
			tmp.data[(i+h2)*tmpW+(j+w2)] = arr->data[i*arrW+j];
		}
	}

	//对输入扩展边界  ‘replicate’	图像大小通过复制外边界的值来扩展
    for(i=0;i<h2;i++)//拓展上面h2 行
        for(j=0;j<tmpW;j++)  
             tmp.data[(i)*tmpW+(j)]   
                =tmp.data[(h2)*tmpW+(j)]   ;  
   
       
        for(i=0;i<h2;i++)//拓展下面h2行  
            for(j=0;j<tmpW;j++)  
                 tmp.data[(i+h2+arrH)*tmpW+(j)]   
                  =tmp.data[(h2+arrH)*tmpW+(j)]   ;  
   
        for(i=0;i<tmpH;i++)//拓展左边w2列  
            for(j=0;j<w2;j++)  
                 tmp.data[(i)*tmpW+(j)]   
                  =tmp.data[(i)*tmpW+(w2)]   ;  
   
        for(i=0;i<tmpH;i++)//拓展右边w2列  
            for(j=0;j<w2;j++)  
                 tmp.data[(i)*tmpW+(j+w2+arrW)]   
                  =tmp.data[(i)*tmpW+(w2+arrW)]   ;  

	//直接'same'切去一部分,让输出与输入图像的大小相同
	for (i=h2; i<h2+arrH; i++)  //输入
    {  
        for (j=w2; j<w2+arrW; j++)  
        {  
            temp = 0;  
            for ( m=0; m<filterH; m++)  //核
            {  
                for (n=0; n<filterW; n++)  
                {  
     //               if ((i-m)>=0 && (i-m)<tmpH && (j-n)>=0 && (j-n)<tmpW)  
     //               {  
                        temp += filter->data[m*filterW+n]*tmp.data[(i-m)*tmpW+(j-n)];  //积 和
					//}else
					//{
					//	
 				//		cout<<"出错了"<<endl;
     //              }  
                }  
            }  
            res->data[(i-h2)*arrW+(j-w2)] = temp; 
        }  
    }  

	
}

效果图:

纯C++超分辨率重建SRCNN --改编--(五)卷积边界填充

基本上和Matlab结果持平了

另外 在 --qq_29058565的博客《图像缩放之双三次插值法》--是2倍放大的,改一下放在这里。

2 倍双三次放大放用到 3 倍模型不知会有怎样效果?

//双三次插值缩放图片

/*
我们要做的就是求出BiCubic函数中的参数x,从而获得上面所说的16个像素所对应的系数。在学习双线性插 
值法的时候,我们是把图像的行和列分开来理解的,那么在这里,我们也用这种方法描述如何求出a(i,j)对应 
的系数k_ij。假设行系数为k_i,列系数为k_j。我们以a00位置为例: 
首先,我们要求出当前像素与P点的位置,比如a00距离P(x+u,y+v)的距离为(1+u,1+v)。 
那么我们可以得到:k_i_0=W(1+u),k_j_0=W(1+v). 
同理我们可以得到所有行和列对应的系数:

k_i_0=W(1+u), k_i_1=W(u), k__i_2=W(1-u), k_i_3=W(2-u); 
k_j_0=W(1+v), k_j_1=W(v), k_j_2=W(1-v), k_j_3=W(2-v);

这样我们就分别得到了行和列方向上的系数。 
由k_i_j=k_i*k_j我们就可以得到每个像素a(i,j)对应的权值了。

最后通过求和公式可以得到目标图片B(X,Y)对应的像素值: 
pixelB(X,Y)=pixelA(0,0)*k_0_0+pixelA(0,1)*k_0_1+…+pixelA(3,3)*k_3_3; 
这里其实就是个求和公式,由于不知道怎么编辑公式,就这样表达了。
*/

/**********************10-9*******************************
功能:双三次插值缩放图片
数学原理:假设原图像A的大小为m*n,新图像B的大小为M*N
如果我们要求B(X,Y)处的像素值:
我们首先可以得到B(X,Y)在图像A中对应的位置(x,y)=(X*(m/M),Y*(N/n))
这个时候求得的x,y是小数值,我们可以通过这个小数值坐标找到距离最近的16个像素点,
利用所选择的基函数,求出对应的每个像素的权值,最终获得pixelB(X,Y)
**********************************************************/

//#include <opencv2\opencv.hpp>
//#include <iostream>
//#include <math.h>
//using namespace std;
//using namespace cv;

//BiCubic基函数
void getW_x(float w_x[4], float x);
void getW_y(float w_y[4], float y);

int 双三次2倍(IMAGE *imgs)
//int main(){
{
    //Mat image = imread("lena.jpg");//源图像
	float image_rows = imgs->getwidth();
	float image_cols = imgs->getheight();

    float Row_B = image_rows*2;
    float Col_B = image_cols*2;

	卷积矩阵 image= im2卷积矩阵(imgs);
	卷积矩阵 biggerImage(Row_B, Col_B);

	Row_B=biggerImage.width;
	Col_B=biggerImage.height ;

   // Mat biggerImage(Row_B, Col_B, CV_8UC3);

    for (int i = 2; i < Row_B-4; i++){
        for (int j = 2; j < Col_B-4; j++){
            float x = i*(image_rows / Row_B);//放大后的图像的像素位置相对于源图像的位置
            float y = j*(image_cols / Col_B);

            /*if (int(x) > 0 && int(x) < image_rows - 2 && int(y)>0 && int(y) < image_cols - 2){*/
                float w_x[4], w_y[4];//行列方向的加权系数
                getW_x(w_x, x);
                getW_y(w_y, y);

                //Vec3f temp = { 0, 0, 0 };
				float temp = 0;
                for (int s = 0; s <= 3; s++){
                    for (int t = 0; t <= 3; t++){
                        //temp = temp + (Vec3f)(image.at<Vec3b>(int(x) + s - 1, int(y) + t - 1))*w_x[s] * w_y[t];
                        temp = temp + image.data[(int(x) + s - 1)*image_rows+( int(y) + t - 1)]*w_x[s] * w_y[t];
                    }
                }

                //biggerImage.at<Vec3b>(i, j) = (Vec3b)temp;
                biggerImage.data[i*Row_B+ j] = temp;
            }
        }

    //imshow("image", image);
    //imshow("biggerImage", biggerImage);
    //waitKey(0);
	IMAGE tt= 卷积矩阵2im(&biggerImage);
	*imgs=tt;
	return 0;
}
/*计算系数*/
void getW_x(float w_x[4],float x){
	float a = -0.5;
    int X = (int)x;//取整数部分
    float stemp_x[4];
    stemp_x[0] = 1 + (x - X);
    stemp_x[1] = x - X;
    stemp_x[2] = 1 - (x - X);
    stemp_x[3] = 2 - (x - X);

    w_x[0] = a*abs(stemp_x[0] * stemp_x[0] * stemp_x[0]) - 5 * a*stemp_x[0] * stemp_x[0] + 8 * a*abs(stemp_x[0]) - 4 * a;
    w_x[1] = (a + 2)*abs(stemp_x[1] * stemp_x[1] * stemp_x[1]) - (a + 3)*stemp_x[1] * stemp_x[1] + 1;
    w_x[2] = (a + 2)*abs(stemp_x[2] * stemp_x[2] * stemp_x[2]) - (a + 3)*stemp_x[2] * stemp_x[2] + 1;
    w_x[3] = a*abs(stemp_x[3] * stemp_x[3] * stemp_x[3]) - 5 * a*stemp_x[3] * stemp_x[3] + 8 * a*abs(stemp_x[3]) - 4 * a;
}
void getW_y(float w_y[4], float y){
	float a = -0.5;
    int Y = (int)y;
    float stemp_y[4];
    stemp_y[0] = 1.0 + (y - Y);
    stemp_y[1] = y - Y;
    stemp_y[2] = 1 - (y - Y);
    stemp_y[3] = 2 - (y - Y);

    w_y[0] = a*abs(stemp_y[0] * stemp_y[0] * stemp_y[0]) - 5 * a*stemp_y[0] * stemp_y[0] + 8 * a*abs(stemp_y[0]) - 4 * a;
    w_y[1] = (a + 2)*abs(stemp_y[1] * stemp_y[1] * stemp_y[1]) - (a + 3)*stemp_y[1] * stemp_y[1] + 1;
    w_y[2] = (a + 2)*abs(stemp_y[2] * stemp_y[2] * stemp_y[2]) - (a + 3)*stemp_y[2] * stemp_y[2] + 1;
    w_y[3] = a*abs(stemp_y[3] * stemp_y[3] * stemp_y[3]) - 5 * a*stemp_y[3] * stemp_y[3] + 8 * a*abs(stemp_y[3]) - 4 * a;
}

效果图:

纯C++超分辨率重建SRCNN --改编--(五)卷积边界填充  纯C++超分辨率重建SRCNN --改编--(五)卷积边界填充  纯C++超分辨率重建SRCNN --改编--(五)卷积边界填充

啊,咋会这样呢?放大就有黑块,可能是我哪里翻译错了吧。

先这样吧。

上一篇:

下一篇: