• 【图像处理】第一次实验:图像的基本运算


    1、任务说明

    打开一幅图像,进行直方图均衡。将灰度线性变化,将灰度拉伸。

    2、算法原理

    1)        图像灰度化

      在RGB模型中,如果R=G=B时,则彩色表示一种灰度颜色,其中R=G=B的值叫做灰度值,灰度范围为0-255。一般有四种方法对彩色进行灰度化,分别为:

    分量法,最大值法,平均值法和加权平均法。本实验中采用平均值法,即

               

    2)        直方图均衡

      直方图表示数字图像中每一个灰度级与其出现频率间的统计关系。设有某一个灰度等级,属于该灰度等级的像素个数为nk,图像总像素个数为n,则直方图的定义为

                      

          图像的直方图反映了图像的灰度范围、灰度分布、图像的平均亮度等。

      直方图均衡化也叫直方图均匀化,其目的是使所有灰度级出现的相对频率表相同,此时图像的熵最大,图像所包含的信息量最大。

      本实验处理在离散情况下的直方图修正。其中第k个灰度级出现的概率为:

                 

      进行均匀化处理的变换函数为:

                   

          由新rk得到均衡化处理后的直方图。

      

    3)        线性变化

      设输入图像的的灰度范围为[a,b],希望经过变换后的输出图像的灰度范围变化为[c,d],则变换函数T的表达式可以表示为

                  

      根据不同的线性变换的斜率和截距,可以达到对图像不同的处理效果。当斜率大于1时,可以增加图像的对比度;当斜率在0与1之间时,

    图像的对比度和整体效果都被削弱,灰度会被集中在一段区域上,灰度取值变窄,使图片趋于灰色。当斜率为负时,源图像较亮的区域变暗,

    较暗的区域变量,可以实现反色效果。而当截距为正时,图像的亮度将会增加;截距为负时,图像的亮度将会降低。

    4)        灰度拉伸(分段线性变化)

      为了突出感兴趣的目标或灰度区间,相对一致不感兴趣的灰度区间,可以采用分段线性变换。本实验采用常用的三段线性变换方法。

                           

      具体算法如下:

                

    3、算法实现

    1)        图像灰度化

    public void turnGray()
    	{
    		for (int i=minx;i<width;i++)
    		{
    			for(int j=miny;j<height;j++)
    			{
    				int pixel=bi.getRGB(i,j);//获得8位的RGB值
    				int a = (pixel >> 24) & 0xff;  //提取前两位透明度
    	            int r = (pixel >> 16) & 0xff;  //提取次两位,R值
    	            int g = (pixel >> 8) & 0xff;  //提取再次两位,G值
    	            int b = pixel & 0xff;  //提取最后两位,B值
    	            int gray=(r+g+b)/3;   //计算平均值,得到像素灰度
                    //根据灰度得到完整8位RGB值
    	            pixel= (a<<24)|(gray<<16)|(gray<<8)|gray;
                    //将新的RGB值赋给像素点
    	            bi.setRGB(i, j,pixel);
    			}
    		}
    		//输出图像
    		try{
    			ImageIO.write(bi, "jpg", new File("D://gray.jpg"));
    		}catch(IOException e)
    		{
    			e.printStackTrace();
    		}
    	}
    

      

    2)        直方图均衡

    public void histEqua()
    	{
    		int[] gray = new int[sum]; //保存初始灰度值
    		int[] newgray = new int[sum]; //保存新灰度值
    		int[] oldgrayscale = new int[256]; //保存灰度累加值
    		double[] grayscale = new double[256];
    		double[] cumulative = new double[256];
    		//统计所有像素中各灰度值出现的次数
    		for(int i=minx;i<width;i++){ 
    			for(int j=miny;j<height;j++){ 
    				int pixel=bi.getRGB(i, j);
    				gray[height*i+j] = (pixel & 0xff);
    				oldgrayscale[gray[height*i+j]]++;	
    			} 
    		}
    		for(int i=0;i<256;i++){
                 //计算原直方图中各灰度值出现的频率
    			grayscale[i] = ((double)oldgrayscale[i])/sum;	
    			for(int j=0;j<=i;j++){
                     //计算累加后的直方图
    				cumulative[i] += grayscale[j];
    			}
                 //得到新的映射关系
    			cumulative[i] = (int)(cumulative[i]*256);	
    		}
    		
    		BufferedImage hist_equa = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
    		//根据累加数组得到新的像素灰度
    		for(int i=minx;i<width;i++){ 
    			for(int j=miny;j<height;j++){ 
    				newgray[height*i+j] = (int)cumulative[gray[height*i+j]];	
    				int pixel = (newgray[height*i+j])|(newgray[height*i+j]<<8)|(newgray[height*i+j]<<16);
    					hist_equa.setRGB(i, j, pixel);
    			} 
    		}
    //输出图像
    		try {
    			ImageIO.write(hist_equa,"jpg", new File("D://histEqua.jpg"));
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    

      

    3)        线性变换

    public void linTrans()
    	{
             //得到线性变换函数的斜率和截距
    		double slope;
    		double intercept;
    		Scanner in = new Scanner(System.in);
    		System.out.println("输入线性变换斜率:");
    		slope=in.nextDouble();
    		System.out.println("输入线性变换截距:");
    		intercept=in.nextDouble();
    		
    		BufferedImage lt =new BufferedImage(width,height,BufferedImage.TYPE_INT_BGR);
    		for(int i=minx;i<width;i++)
    		{
    			for(int j=miny;j<height;j++)
    			{
                 //提取灰度值
    				int pixel = bi.getRGB(i, j);
    				pixel = pixel & 0xff;
                 //进行线性变换
    				pixel = (int)(pixel*slope + intercept);
                 //对超出边界的值进行处理
    				if(pixel<0)
    					pixel=0;
    				if(pixel>255)
    					pixel=255;
                 //恢复为RGB值
    				pixel = (pixel<<16)|(pixel<<8)|pixel;
    				lt.setRGB(i, j, pixel);
    			}
    		}
            //输出图像
    		try {
    			ImageIO.write(lt,"jpg", new File("D://linTrans.jpg"));
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		
    	}
    

      

    4)        灰度拉伸

    public void linStr()
    	{
    		int x1,x2,y1,y2;
    		double k1,k2,b1,b2,k3,b3;
    		//读入线性变换两份转折点的坐标
    		Scanner in = new Scanner(System.in);
    		System.out.println("输入灰度拉伸第一个点的坐标,以空格分开:");
    		x1 = in.nextInt();
    		y1 = in.nextInt();
    		System.out.println("输入灰度拉伸第二个点的坐标,以空格分开:");
    		x2 = in.nextInt();
    		y2 = in.nextInt();
    		in.close();
    		//计算三段线性变换各阶段的斜率与截距
    		k1 = y1/x1;
    		b1 = 0;
    		k2 = (y2-y1)/(x2-x1);
    		b2 = y1-k2*x1;
    		k3 = (255-y2)/(255-x2);
    		b3 = y2-k3*x2;
    		 
    		
    		BufferedImage ls =new BufferedImage(width,height,BufferedImage.TYPE_INT_BGR);
    		for(int i=minx;i<width;i++)
    		{
    			for(int j=miny;j<height;j++)
    			{//提取像素点灰度值
    				int pixel = bi.getRGB(i, j);
    				pixel = pixel & 0xff;
                  //分段进行线性变化
    				if(pixel<x1)
    					pixel = (int)(pixel*k1  + b1);
    				else if(pixel>=x2)
    					pixel = (int)(pixel*k3  + b3);
    				else
    					pixel = (int)(pixel*k2  + b2);
    				//对于超出边界的值进行处理
    				if(pixel<0)
    					pixel=0;
    				if(pixel>255)
    					pixel=255;
    				pixel = (pixel<<16)|(pixel<<8)|pixel;
    				ls.setRGB(i, j, pixel);
    			}
    		}
            //输出图像
    		try {
    			ImageIO.write(ls,"jpg", new File("D://linStr.jpg"));
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    	
    	private BufferedImage bi=null;
    	private int width;
    	private int height; 
    	private int minx; 
    	private int miny;
    	private int sum;
    
    }
    

      

    4、实验

                    源图像                                   灰度图像                            

                直方图均衡化                  (-1,255)线性变换,相当于反色        

       灰度拉伸,某些像素得到凸显

  • 相关阅读:
    扩展DigitalClock显示日期+时间
    利用Handler定时更新Android UI
    CheckBox在表格中全选、部分选和反选
    jQuery实现表格间隔色
    Android中对话框(dialog)的使用
    The connection to adb is down, and a severe error has occured.
    struts2类型转化
    Android开发之旅:环境搭建及HelloWorld
    C/C++浮点数在内存中的存储方式
    用标签写登录界面
  • 原文地址:https://www.cnblogs.com/libcan/p/3703852.html
Copyright © 2020-2023  润新知