zoukankan      html  css  js  c++  java
  • html5图像、图片处理【转】

    本文主题

          情人节在网上看到国外JS牛人利用HTML5技术实现的一朵玫瑰花,深切的感受到HTML5技术的强大。本着学习的态度看了一下那朵玫瑰花的源代码,其中用到的HTML5技术是canvas标签,于是灵光一现,想试一下能不能进行图像处理,结果成功了,再次介绍一下经验。

          本文的思路是获取一张带有验证码的图片,然后对其进行灰度化操作,完成后对其使用Otsu算法进行二值化操作,最后输出二值化的图片,其效果图如下:

    image

                图1

    最后友情提醒一下,HTML5技术在IE浏览器下面不支持或者是没有全面支持,因此如要进行HTML5开发请使用火狐或者是谷歌等支持的浏览器。

    显示图像

    在页面中引入canvas标签,并设置其id属性,在脚本中使用getElementById()来获取标签的句柄。

    function drawImage(){
    
    //获取标签的句柄
    
    var canvas = document.getElementById('myCanvasElt');
    
    //获取绘图的上下文
    
    var ctx = canvas.getContext('2d');
    
    //新建一个image,目的是为了读取图片
    
    var img=new Image()
    
    img.src="image/VerifyCode.jpg"
    
    //将image中的图片绘制到canvas中
    
    ctx.drawImage(img,0,0);
    
    }

    以上代码实现了图1中原图像的显示。

    灰值化图像

    对图像进行灰值化的过程就是将一幅图像的RGB三个属性设为一致的过程,即去掉图像的颜色信息,使用灰度信息表达图像的内容。彩色转灰度图像有几种算法:

    1.加权平均法。Gray = R*0.299 + G*0.587 + B*0.114

    2.平均值法。Gray = ( R + G + B )/3

    3.最大值法。Gray  = Max(R,G,B)

    其中R,G,B表示图像三个分量的值,上述三种算法的好坏对比在这里不做解释,详细资料请参阅彩色图像灰度化。本文采用第一种方法。

    //彩色图像灰度化
    
    function ProcessToGrayImage(){
    
    	var canvas = document.getElementById('myCanvasElt');
    
    	var ctx = canvas.getContext('2d');	
    
    	//取得图像数据
    
            var canvasData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    
    	//这个循环是取得图像的每一个点,在计算灰度后将灰度设置给原图像
    
            for (var x = 0; x < canvasData.width; x++) {
    
    	    for (var y = 0; y < canvasData.height; y++) {
    
    	        // Index of the pixel in the array
    
    	        var idx = (x + y * canvas.width) * 4;
    
    	        // The RGB values
    
    	        var r = canvasData.data[idx + 0];
    
    	        var g = canvasData.data[idx + 1];
    
    	        var b = canvasData.data[idx + 2];
    
    	        //更新图像数据
    
    	        var gray = CalculateGrayValue(r , g , b);
    
    	        canvasData.data[idx + 0] = gray;
    
    	        canvasData.data[idx + 1] = gray;
    
    	        canvasData.data[idx + 2] = gray;
    
    	    }
    
    	}
    
    	ctx.putImageData(canvasData, 0, 0);
    
    }
    
    //计算图像的灰度值,公式为:Gray = R*0.299 + G*0.587 + B*0.114
    
     function CalculateGrayValue(rValue,gValue,bValue){
    
     	   return parseInt(rValue * 0.299 + gValue * 0.587 + bValue * 0.114);
    
     	}	

    Otsu算法

    关于Otsu算法的具体理论在这里不再讲解。这是一种二值化速度很快的图像分割算法。后面会把该算法的理论详细说明。使用javascript算法实现的过程如下:

    //一维OTSU图像处理算法
    
     function OTSUAlgorithm(){
    
       var m_pFstdHistogram = new Array();//表示灰度值的分布点概率
    
       var m_pFGrayAccu = new Array();//其中每一个值等于m_pFstdHistogram中从0到当前下标值的和
    
       var m_pFGrayAve = new Array();//其中每一值等于m_pFstdHistogram中从0到当前指定下标值*对应的下标之和
    
       var m_pAverage=0;//值为m_pFstdHistogram【256】中每一点的分布概率*当前下标之和
    
       var m_pHistogram = new Array();//灰度直方图
    
       var i,j;
    
       var temp=0,fMax=0;//定义一个临时变量和一个最大类间方差的值
    
       var nThresh = 0;//最优阀值
    
       //获取灰度图像的信息
    
       var imageInfo = GetGrayImageInfo();
    
       if(imageInfo == null){
    
         window.alert("图像还没有转化为灰度图像!");
    
         return;
    
       }
    
       //初始化各项参数
    
       for(i=0; i<256; i++){
    
         m_pFstdHistogram[i] = 0;
    
         m_pFGrayAccu[i] = 0;
    
         m_pFGrayAve[i] = 0;
    
         m_pHistogram[i] = 0;
    
       }
    
       //获取图像信息
    
       var canvasData = imageInfo[0];
    
       //获取图像的像素
    
       var pixels = canvasData.data;
    
       //下面统计图像的灰度分布信息
    
       for(i=0; i<pixels.length; i+=4){
    
          //获取r的像素值,因为灰度图像,r=g=b,所以取第一个即可
    
          var r = pixels[i];
    
          m_pHistogram[r]++;
    
       }
    
       //下面计算每一个灰度点在图像中出现的概率
    
       var size = canvasData.width * canvasData.height;
    
       for(i=0; i<256; i++){
    
          m_pFstdHistogram[i] = m_pHistogram[i] / size;
    
       }
    
       //下面开始计算m_pFGrayAccu和m_pFGrayAve和m_pAverage的值
    
       for(i=0; i<256; i++){
    
          for(j=0; j<=i; j++){
    
            //计算m_pFGaryAccu[256]
    
    		m_pFGrayAccu[i] += m_pFstdHistogram[j];
    
    		//计算m_pFGrayAve[256]
    
    		m_pFGrayAve[i] += j * m_pFstdHistogram[j];
    
          }
    
          //计算平均值
    
    	  m_pAverage += i * m_pFstdHistogram[i];
    
       }
    
       //下面开始就算OSTU的值,从0-255个值中分别计算ostu并寻找出最大值作为分割阀值
    
       for (i = 0 ; i < 256 ; i++){
    
    		temp = (m_pAverage * m_pFGrayAccu[i] - m_pFGrayAve[i]) 
    
    		     * (m_pAverage * m_pFGrayAccu[i] - m_pFGrayAve[i]) 
    
    		     / (m_pFGrayAccu[i] * (1 - m_pFGrayAccu[i]));
    
    		if (temp > fMax)
    
    		{
    
    			fMax = temp;
    
    			nThresh = i;
    
    		}
    
    	}
    
       //下面执行二值化过程 
    
       for(i=0; i<canvasData.width; i++){
    
          for(j=0; j<canvasData.height; j++){
    
             //取得每一点的位置
    
             var ids = (i + j*canvasData.width)*4;
    
             //取得像素的R分量的值
    
             var r = canvasData.data[ids];
    
             //与阀值进行比较,如果小于阀值,那么将改点置为0,否则置为255
    
             var gray = r>nThresh?255:0;
    
             canvasData.data[ids+0] = gray;
    
             canvasData.data[ids+1] = gray;
    
             canvasData.data[ids+2] = gray;
    
          }
    
       }
    
       //显示二值化图像
    
       var newImage = document.getElementById('myCanvasThreshold').getContext('2d');
    
       newImage.putImageData(canvasData,0,0);
    
     }	
    
     
    
     //获取图像的灰度图像的信息
    
     function GetGrayImageInfo(){
    
        var canvas = document.getElementById('myCanvasElt');
    
    	var ctx = canvas.getContext('2d');
    
    	var canvasData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    
    	if(canvasData.data.length==0){
    
    	  return null;
    
    	}
    
    	return [canvasData,ctx];
    
     }
    
     //下面对灰度图像进行处理,将目标信息分割出来
    
     function DividedTarget(){
    
       //读取二值化图像信息
    
       var imageInfo = document.getElementById('myCanvasThreshold');
    
       if(imageInfo == null){
    
         window.alert("没有发现二值化图像信息!");
    
         return;
    
       }
    
       //取得上下文
    
       var ctx = imageInfo.getContext('2d');
    
       //获取图像数据
    
       var canvasData = imageInfo.getImageData(0, 0, ctx.width, ctx.height);
    
       var newVanvasData = canvasData;
    
       //取得图像的宽和高
    
       var width = canvasData.width;
    
       var height = canvasData.height;
    
       //算法开始
    
       var cursor = 2;
    
       for(var x=0; x<width; x++){
    
          for(var y=0; y<height; y++){
    
             //取得每一点的位置
    
             var ids = (x + y*canvasData.width)*4;
    
             //取得像素的R分量的值
    
             var r = canvasData.data[ids];
    
             //如果是目标点
    
             if(r==0){
    
                
    
             }
    
          }
    
       }
    
       
    
     }

          算法的实现中给出了详细的注释,如果有不清楚的地方可以留言或者发邮件咨询,值得注意的是,由于js不允许跨域访问的特性,要想成功运行上面的代码,必须将它运行在一个服务器中,比如说Apache。

    代码详单

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    
    <html>
    
      <head>
    
        <title>gray.html</title>
    
    	
    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    
        <meta http-equiv="description" content="this is my page">
    
        <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    
        
    
        <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->
    
    <script type="text/javascript">
    
    function ProcessToGrayImage(){
    
    	var canvas = document.getElementById('myCanvasElt');
    
    	var ctx = canvas.getContext('2d');
    
    	var img=new Image()
    
    	img.src="image/VerifyCode.jpg"
    
    	ctx.drawImage(img,0,0);
    
    	
    
    	var canvasData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    
    	for (var x = 0; x < canvasData.width; x++) {
    
    	    for (var y = 0; y < canvasData.height; y++) {
    
    	        // Index of the pixel in the array
    
    	        var idx = (x + y * canvas.width) * 4;
    
    	        // The RGB values
    
    	        var r = canvasData.data[idx + 0];
    
    	        var g = canvasData.data[idx + 1];
    
    	        var b = canvasData.data[idx + 2];
    
    	        // Update the values of the pixel;
    
    	        var gray = CalculateGrayValue(r , g , b);
    
    	        canvasData.data[idx + 0] = gray;
    
    	        canvasData.data[idx + 1] = gray;
    
    	        canvasData.data[idx + 2] = gray;
    
    	    }
    
    	}
    
    	ctx.putImageData(canvasData, 0, 0);
    
    }
    
    //计算图像的灰度值,公式为:Gray = R*0.299 + G*0.587 + B*0.114
    
     function CalculateGrayValue(rValue,gValue,bValue){
    
     	   return parseInt(rValue * 0.299 + gValue * 0.587 + bValue * 0.114);
    
     	}	
    
     //一维OTSU图像处理算法
    
     function OTSUAlgorithm(){
    
       var m_pFstdHistogram = new Array();//表示灰度值的分布点概率
    
       var m_pFGrayAccu = new Array();//其中每一个值等于m_pFstdHistogram中从0到当前下标值的和
    
       var m_pFGrayAve = new Array();//其中每一值等于m_pFstdHistogram中从0到当前指定下标值*对应的下标之和
    
       var m_pAverage=0;//值为m_pFstdHistogram【256】中每一点的分布概率*当前下标之和
    
       var m_pHistogram = new Array();//灰度直方图
    
       var i,j;
    
       var temp=0,fMax=0;//定义一个临时变量和一个最大类间方差的值
    
       var nThresh = 0;//最优阀值
    
       //获取灰度图像的信息
    
       var imageInfo = GetGrayImageInfo();
    
       if(imageInfo == null){
    
         window.alert("图像还没有转化为灰度图像!");
    
         return;
    
       }
    
       //初始化各项参数
    
       for(i=0; i<256; i++){
    
         m_pFstdHistogram[i] = 0;
    
         m_pFGrayAccu[i] = 0;
    
         m_pFGrayAve[i] = 0;
    
         m_pHistogram[i] = 0;
    
       }
    
       //获取图像信息
    
       var canvasData = imageInfo[0];
    
       //获取图像的像素
    
       var pixels = canvasData.data;
    
       //下面统计图像的灰度分布信息
    
       for(i=0; i<pixels.length; i+=4){
    
          //获取r的像素值,因为灰度图像,r=g=b,所以取第一个即可
    
          var r = pixels[i];
    
          m_pHistogram[r]++;
    
       }
    
       //下面计算每一个灰度点在图像中出现的概率
    
       var size = canvasData.width * canvasData.height;
    
       for(i=0; i<256; i++){
    
          m_pFstdHistogram[i] = m_pHistogram[i] / size;
    
       }
    
       //下面开始计算m_pFGrayAccu和m_pFGrayAve和m_pAverage的值
    
       for(i=0; i<256; i++){
    
          for(j=0; j<=i; j++){
    
            //计算m_pFGaryAccu[256]
    
    		m_pFGrayAccu[i] += m_pFstdHistogram[j];
    
    		//计算m_pFGrayAve[256]
    
    		m_pFGrayAve[i] += j * m_pFstdHistogram[j];
    
          }
    
          //计算平均值
    
    	  m_pAverage += i * m_pFstdHistogram[i];
    
       }
    
       //下面开始就算OSTU的值,从0-255个值中分别计算ostu并寻找出最大值作为分割阀值
    
       for (i = 0 ; i < 256 ; i++){
    
    		temp = (m_pAverage * m_pFGrayAccu[i] - m_pFGrayAve[i]) 
    
    		     * (m_pAverage * m_pFGrayAccu[i] - m_pFGrayAve[i]) 
    
    		     / (m_pFGrayAccu[i] * (1 - m_pFGrayAccu[i]));
    
    		if (temp > fMax)
    
    		{
    
    			fMax = temp;
    
    			nThresh = i;
    
    		}
    
    	}
    
       //下面执行二值化过程 
    
       for(i=0; i<canvasData.width; i++){
    
          for(j=0; j<canvasData.height; j++){
    
             //取得每一点的位置
    
             var ids = (i + j*canvasData.width)*4;
    
             //取得像素的R分量的值
    
             var r = canvasData.data[ids];
    
             //与阀值进行比较,如果小于阀值,那么将改点置为0,否则置为255
    
             var gray = r>nThresh?255:0;
    
             canvasData.data[ids+0] = gray;
    
             canvasData.data[ids+1] = gray;
    
             canvasData.data[ids+2] = gray;
    
          }
    
       }
    
       //显示二值化图像
    
       var newImage = document.getElementById('myCanvasThreshold').getContext('2d');
    
       newImage.putImageData(canvasData,0,0);
    
     }	
    
     
    
     //获取图像的灰度图像的信息
    
     function GetGrayImageInfo(){
    
        var canvas = document.getElementById('myCanvasElt');
    
    	var ctx = canvas.getContext('2d');
    
    	var canvasData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    
    	if(canvasData.data.length==0){
    
    	  return null;
    
    	}
    
    	return [canvasData,ctx];
    
     }
    
     //下面对灰度图像进行处理,将目标信息分割出来
    
     function DividedTarget(){
    
       //读取二值化图像信息
    
       var imageInfo = document.getElementById('myCanvasThreshold');
    
       if(imageInfo == null){
    
         window.alert("没有发现二值化图像信息!");
    
         return;
    
       }
    
       //取得上下文
    
       var ctx = imageInfo.getContext('2d');
    
       //获取图像数据
    
       var canvasData = imageInfo.getImageData(0, 0, ctx.width, ctx.height);
    
       var newVanvasData = canvasData;
    
       //取得图像的宽和高
    
       var width = canvasData.width;
    
       var height = canvasData.height;
    
       //算法开始
    
       var cursor = 2;
    
       for(var x=0; x<width; x++){
    
          for(var y=0; y<height; y++){
    
             //取得每一点的位置
    
             var ids = (x + y*canvasData.width)*4;
    
             //取得像素的R分量的值
    
             var r = canvasData.data[ids];
    
             //如果是目标点
    
             if(r==0){
    
                
    
             }
    
          }
    
       }
    
       
    
     }
    
    </script>
    
      </head>
    
      
    
      <body>
    
      原图像:<br/>
    
      <img src="image/VerifyCode.jpg" /><br/>
    
      灰度图像:<input type="button" value="处理" onclick="javascript:ProcessToGrayImage();" /><br/>
    
      <canvas id="myCanvasElt" width="200" height="100"></canvas><br/>
    
      二值化图像:<input type="button" value="二值化" onclick="javascript:OTSUAlgorithm();" /><br/>
    
      <canvas id="myCanvasThreshold" width="200" height="100"></canvas><br/>
    
      </body>
    
    </html>
    

    总结说明

  • 相关阅读:
    记录-java(jxl) Excel导入数据库
    记录--Gson、json转实体类、类转json
    记录--java获取网络资源(图片、音频等)保存本地
    记录--指定路径复制文件到另一个路径
    记录-java执行请求的URL
    记录-Hibernate+servlet实现简单的增、删、查、改
    我的学习之路_第二十八章_JQuery 和validator插件
    我的学习之路_第二十七章_jQuery
    我的学习之路_第二十六章_javaScript(2)
    我的学习之路_第二十五_javaScript
  • 原文地址:https://www.cnblogs.com/fx2008/p/4233151.html
Copyright © 2011-2022 走看看