图像缩放之最近邻插值

最近邻插值
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
using namespace std;
typedef unsigned short WORD;
typedef unsigned long DWORD;
#pragma pack(1)
typedef struct
BMP_FILE_HEADER
{
    
    
	WORD bType;
	DWORD bSize;
	WORD bReserved1;
	WORD bReserved2;
	DWORD bOffset;
}BMPFILEHEADER;
//文件头信息
#pragma pack(1)
typedef struct BMP_INFO
{
    
    
	DWORD bInfoSize;
	DWORD bWidth;
	DWORD bHeight;
	WORD bPlanes;
	WORD bBitCount;
	DWORD bCompression;
	DWORD bmpImageSize;
	DWORD bXPelsPerMeter;
	DWORD bYPelsPerMeter;
	DWORD bClrUsed;
	DWORD bClrImportant;
}BMPINF;
unsigned char*pBmpBuf;
unsigned char*pBmpBuf1;
bool saveBmp(char*bmpName,unsigned char*imgBuf,int width,int height,int biBitCount,RGBQUAD*pColorTable)
{
    
    
	int biHeight=512,biWidth=512;
	FILE*fp1=fopen("F:\\33\\lena.bmp","rb+");
	//如果位图数据指针为0,则没有数据传入,函数返回
	if(!imgBuf)
		return 0;
	//灰度图像颜色表为1024字节,彩色图像颜色表大小为0
	int colorTablesize=0;
	if(biBitCount==8){
    
    colorTablesize=1024;}
	//待存储图像数据每行字节数为4的倍数
	int lineByte=(width*biBitCount/8+3)/4*4;
	//以二进制写的方式打开文件
//FILE*fp=fopen(bmpName,"wb");
	FILE*fp2=fopen("F:\\33\\lena.bmp","wb+");
	if(fp2==0)return 0;
	//申请位图文件头结构变量,填写文件头信息
	BITMAPFILEHEADER fileHead;
	fileHead.bfType=0x4D42;//bmp类型
	//bfSize是图像文件4个组成部分之和
	fileHead.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)
		+colorTablesize+lineByte*height;
	fileHead.bfReserved1=0;
	fileHead.bfReserved2=0;
	fileHead.bfOffBits=54+colorTablesize;
	//写文件头进文件
	fwrite(&fileHead,sizeof(BITMAPFILEHEADER),1,fp2);
	BITMAPINFOHEADER head;
	head.biBitCount=biBitCount;
	head.biClrImportant=0;
	head.biClrUsed=0;
	head.biCompression=0;
	head.biHeight=height;
	head.biPlanes=1;
	head.biSize=40;
	head.biSizeImage=lineByte*height;
	head.biWidth=width;
	head.biXPelsPerMeter=0;
	head.biYPelsPerMeter=0;
	//写位图信息头进内存
	fwrite(&head,sizeof(BITMAPINFOHEADER),1,fp2);
	//如果灰度图像,有颜色表,写入文件
	BYTE p[4]={
    
    };p[3]=0;
	if(biBitCount==8)
		for(int i=0;i<256;i++)
		{
    
    
			p[0]=p[1]=p[2]=i;
			fwrite((void*)p,1,4,fp2);
		}
	//写位图数据进文件
	int j=(biWidth*biBitCount/8+3)/4*4;
	fseek(fp1,-j*biHeight,2);
	long q;
	if((q=ftell(fp1))==-1L)
	{
    
    
		puts("GetBitmapHeader读取文件指针位置失败!");
		return 0;
	}
	else{
    
    printf("起始字节:%d\n",q);}
	pBmpBuf1=new unsigned char[lineByte*biHeight];
	int a;int b=0;
	for(a=0;a<biHeight*biHeight;a++)
	{
    
    
		fread(pBmpBuf1,1,1,fp1);
		fseek(fp1,1,1);
		b++;
		if(b==256)
		{
    
    
			fseek(fp1,biHeight,1);
			b=0;
		}
		fwrite(pBmpBuf1,1,1,fp2);
	}
	fclose(fp2);
	fclose(fp1);
	return 1;
}
int main()
{
    
    
	FILE*fp;
	BMPFILEHEADER FileHead;
	BMPINF bmpinfo;
	if((fp=fopen("F:\\33\\lena.bmp","rb"))==NULL)//fp=0x00426aa0
	{
    
    
		printf("Cann't open the file!\n");
		return 0;
	}
	fseek(fp,0,SEEK_SET);
	fread(&FileHead,sizeof(BMPFILEHEADER),1,fp);

	fread(&bmpinfo,sizeof(bmpinfo),1,fp);
	int lineByte=(bmpinfo.bWidth*bmpinfo.bBitCount/8+3)/4*4;
	char writePath[]="F:\\33\\lena.bmp";
	RGBQUAD*pColorTable
		=NULL;
	pBmpBuf=new unsigned char[lineByte*bmpinfo.bHeight];
	fread(pBmpBuf,1,lineByte*bmpinfo.bHeight,fp);
	fclose(fp);
	saveBmp(writePath,pBmpBuf,bmpinfo.bWidth/2,bmpinfo.bHeight/2,bmpinfo.bBitCount,pColorTable);
	system("pause");
	return 0;
}
双线性插值法
int x1,x2,y1,y2,Fq11,Fq12,Fq21,Fq22;
double x,y,r1,Fr1,Fr2,Fp;
for(int i=0;i<dstHeight;++i){
    
    
for(int j=0;j<dstWidth;++j){
    
    unsigned char*p1,*p2;
x=1/lx*j;//原图像坐标
y=1/ly*i;
//四个坐标值
x1=floor(x);x2=x1+1;//
y1=floor(y);y2=y1+1;
//四个坐标对应的灰度值
Fq11=*(pBmpBuf+y1*lineByte+x1);
Fq12=*(pBmpBuf+y2*lineByte+x1);
Fq21=*(pBmpBuf+y1*lineByte+x2);
Fq22=*(pBmpBuf+y2*lineByte+x2);
//x方向插值和y方向插值
Fr1=0;Fr2=0;
Fr1=(x2-x)/(x2-x1)*Fq11+(x-x1)/(x2-x1)*Fq21;
Fr2=(x2-x)/(x2-x1)*Fq12+(x-x1)/(x2-x1)*Fq22;
Fp=(y2-y)/(y2-y1)*Fr1+(y-y1)/(y2-y1)*Fr2;
//新图像灰度值赋值
if(Fp>=0&&Fp<=255){
    
    
p1=(unsigned char*)(pBmpBuf2+i*lineByte2+j);//	新图像
(*p1)=round(Fp);
}
}
}

1.1灰度图像最近邻缩放:
(1)读入lena.bmp文件;
(2)采用最近邻方2法将原图长宽各缩小2倍,即隔1点取1点,存为lenas.bmp;
(3)采用最近邻方法将lenas.bmp重新放大到原来的尺寸,存为lenasz.bmp,
比较其余原图lena.bmp的区别;
(4)将缩放倍数改为4重复上述步骤。
1.2灰度图像双线性插值缩放(1)读入文件lena.bmp文件;
(2)采用双线性插值法将图像缩小2倍(将源图像相邻两个像素平均后作为
一个像素),存为lenas1.bmp;
(3)将缩小后的图像放大回原来的尺寸,存为lenasz1.bmp,对比其与原始图像lena.bmp的异同。
(4)将放大倍数改为任意值,重复以上步骤。
1.3将灰度图改为彩色图像重复1、2内容。

用最近邻插值算法实现图像的扩大和缩小任意的尺寸,目标图的任意一点的x,y坐标的像素值取源图最接近x,y坐标的X,Y坐标的像素值,以达到扩大和缩小的目的。
最临近插值算法,这是一种最基本、最简单的图像缩放算法,效果也是最不好的,放大后的图像有很严重的马赛克,缩小后的图像有很严重的失真;效果不好的根源就是其简单的最临近插值方法引入了严重的图像失真,比如,当由目标图的坐标反推得到的源图的的坐标是一个浮点数的时候,采用了四舍五入的方法,直接采用了和这个浮点数最接近的象素的值,这种方法是很不科学的,当推得坐标值为 0.75的时候,不应该就简单的取为1,既然是0.75,比1要小0.25 ,比0要大0.75 ,那么目标象素值其实应该根据这个源图中虚拟的点四周的四个真实的点来按照一定的规律计算出来的,这样才能达到更好的缩放效果。双线型内插值算法就是一种比较好的图像缩放算法,

猜你喜欢

转载自blog.csdn.net/gubeiqing/article/details/112252722
今日推荐