图像插值算法(最近临插值算法)

原文地址:https://blog.csdn.net/mcgrady_tracy/article/details/46625367


对于图像缩放算法来说,最近临插值算法是最简单的。最近临插值算法的原理是在原图像中找到最近临的一个点,然后把这个点的像素值插入到目标图像中,最近临插值算法优点是算法简单,易于实现,但是缺点是由于相邻像素点的像素值相同,容易出现色块现象。

那么如何在原图像中找这个目标点呢,算法公式如下:

src_x = dst_x * (src_width / dst_width);
src_y = dst_y * (src_height / dst_height);

那么算出来呢,可能会是小数点,需要四舍五入取整,那么下面来看一个例子(一个3*3的矩阵):

234     38      22
67      44      12
89      65      63

这里呢,我们需要将上面的一个3*3矩阵变换成一个4*4的矩阵,我们根据上面的公式来计算一下,首先是目标点为(0,0),那么原图像的坐标点为(0,0),那么这个坐标点的值就应该为234,然后再来看(0,1)这个坐标点,那么纵坐标点还是0,但是横坐标点变成了1*(3/4) = 0.75,四舍五入得1,那么得到的原图像坐标为(0,1),那么这个坐标点值就应该为38,同理,最后得到的矩阵结果如下:

234	38	22	22	
67	44	12	12	
89	65	63	63	
89	65	63	63

这部分测试代码如下:

[cpp]  view plain  copy
  1. #include   
  2.   
  3. int main(int argc, char *argv[])  
  4. {  
  5.     int i, j, row, col;  
  6.     unsigned char mat1[3][3] = {{234, 38, 22},  
  7.                     {67, 44, 12},  
  8.                     {89, 65, 63}};  
  9.     unsigned char mat2[4][4];  
  10.       
  11.     for (i = 0; i < 4; i++) {  
  12.         for (j = 0; j < 4; j++) {  
  13.             row = (int)(i * (3.0 / 4.0) + 0.5);  
  14.             col = (int)(j * (3.0 / 4.0) + 0.5);  
  15.             mat2[i][j] = mat1[row][col];  
  16.             printf("%d\t", mat2[i][j]);  
  17.         }  
  18.         printf("\n");  
  19.     }  
  20.   
  21.     return 0;  
  22. }  
关于对于图像的最近临插值算法我也写了一个测试代码(只针对bmp格式的图片,放大两倍):
[cpp]  view plain  copy
  1. #include   
  2. #include   
  3.   
  4. struct bitmap_fileheader {  
  5.     unsigned short  type;  
  6.     unsigned int    size;  
  7.     unsigned short  reserved1;  
  8.     unsigned short  reserved2;  
  9.     unsigned int    off_bits;  
  10. } __attribute__ ((packed));  
  11.   
  12. struct bitmap_infoheader {  
  13.     unsigned int    size;  
  14.     unsigned int    width;  
  15.     unsigned int    height;  
  16.     unsigned short  planes;  
  17.     unsigned short  bit_count;  
  18.     unsigned int    compression;  
  19.     unsigned int    size_image;  
  20.     unsigned int    xpels_per_meter;  
  21.     unsigned int    ypels_per_meter;  
  22.     unsigned int    clr_used;  
  23.     unsigned int    clr_important;  
  24. } __attribute__ ((packed));  
  25.   
  26. void resize_near(void *dst, void *src, int dst_width, int dst_height, int src_width, int src_height)  
  27. {  
  28.     int i, j, x, y;  
  29.     float scale_x, scale_y;  
  30.   
  31.     char *buf1 = (char *)src, *buf2 = (char *)dst;  
  32.   
  33.     scale_x = (float)src_width / (float)dst_width;  
  34.     scale_y = (float)src_height / (float)dst_height;  
  35.   
  36.     for (i = 0; i < dst_height; i++) {  
  37.         for (j = 0; j < dst_width; j++) {  
  38.             y = (int)(i * scale_y + 0.5);  
  39.             x = (int)(j * scale_x + 0.5);  
  40.               
  41.             buf2[i*dst_width*3 + j*3] = buf1[y*src_width*3 + x*3];  
  42.             buf2[i*dst_width*3 + j*3 + 1] = buf1[y*src_width*3 + x*3 + 1];  
  43.             buf2[i*dst_width*3 + j*3 + 2] = buf1[y*src_width*3 + x*3 + 2];  
  44.         }  
  45.     }  
  46. }  
  47.   
  48. int main(int argc, char *argv[])  
  49. {  
  50.     FILE *fp1, *fp2;  
  51.     struct bitmap_fileheader fh;  
  52.     struct bitmap_infoheader ih;  
  53.   
  54.     void *buf1, *buf2;  
  55.   
  56.     int src_width, src_height, dst_width, dst_height;  
  57.   
  58.     if (argc < 2)  
  59.         return -1;  
  60.   
  61.     fp1 = fopen(argv[1], "rb");  
  62.     if (fp1 == NULL) {  
  63.         printf("open file %s failed!\n", argv[1]);  
  64.         return -1;  
  65.     }  
  66.   
  67.     fread(&fh, 1, sizeof(struct bitmap_fileheader), fp1);  
  68.   
  69.     fread(&ih, 1, sizeof(struct bitmap_infoheader), fp1);  
  70.     src_width = ih.width;  
  71.     src_height = ih.height;  
  72.   
  73.     buf1 = malloc(ih.width * ih.height * (ih.bit_count / 8));  
  74.     fread(buf1, 1, ih.width * ih.height * (ih.bit_count / 8), fp1);  
  75.   
  76.     fp2 = fopen("resize.bmp""wb");  
  77.     if (fp2 == NULL) {  
  78.         printf("open file resize.bmp failed!\n");  
  79.         return -1;  
  80.     }  
  81.   
  82.     dst_width = src_width * 2;  
  83.     dst_height = src_height * 2;  
  84.   
  85.     ih.width = dst_width;  
  86.     ih.height = dst_height;  
  87.   
  88.     fh.size = fh.off_bits + ih.width * ih.height * (ih.bit_count / 8);  
  89.     fwrite(&fh, 1, sizeof(struct bitmap_fileheader), fp2);  
  90.   
  91.     fwrite(&ih, 1, sizeof(struct bitmap_infoheader), fp2);  
  92.   
  93.     buf2 = malloc(ih.width * ih.height * (ih.bit_count / 8));  
  94.     resize_near(buf2, buf1, dst_width, dst_height, src_width, src_height);  
  95.   
  96.     fwrite(buf2, 1, ih.width * ih.height * (ih.bit_count / 8), fp2);  
  97.   
  98.     free(buf1);  
  99.   
  100.     free(buf2);  
  101.   
  102.     fclose(fp1);  
  103.   
  104.     fclose(fp2);  
  105.   
  106.     return 0;  
  107. }  

如果用opencv来做,那就很简单了,直接使用opencv提供的cvResize函数,代码如下:

[cpp]  view plain  copy
  1. #include   
  2. #include   
  3.   
  4. int main(int argc, char *argv[])  
  5. {  
  6.     IplImage *img1, *img2;  
  7.   
  8.     if (argc < 2)  
  9.         return -1;  
  10.   
  11.     img1 = cvLoadImage(argv[1]);  
  12.     img2 = cvCreateImage(CvSize(img1->width*2, img1->height*2), img1->depth, img1->nChannels);  
  13.       
  14.     cvResize(img1, img2, CV_INTER_LINEAR);  
  15.                     /*  CV_INTER_NN 
  16.                         CV_INTER_LINEAR 
  17.                         CV_INTER_AREA 
  18.                         CV_INTER_CUBIC */  
  19.   
  20.     cvSaveImage("test.jpg", img2);  
  21.   
  22.     cvReleaseImage(&img1);  
  23.     cvReleaseImage(&img2);  
  24.   
  25.     return 0;  
  26. }  
其中参数CV_INTER_NN对应最近临插值算法,CV_INTER_LINEAR对应双线性插值算法。

你可能感兴趣的:(NDK)