HTML5灰度图像处理练习1:直方图和灰度反转

大多数医学图像都是灰度图像,这个练习也是顺便考察一下HMTL5 Canvas API在医学图像处理方面的潜力。

下面是一个简单的直方图和灰度反转案例。原理是在Canvas中打开一幅gif或jpg的256级灰度图像,通过context.getImageData()获得象素矩阵。然后,对这个象素矩阵进行统计,可以生成直方图。或者,对这个矩阵进行灰度反转之后,用context.putImageData()重新显示出来。顺带提一下,画直方图的时候,我是直接在imagedata的象素矩阵上画线的,而没有用lineTo之类的API,因为我发现后者画出来的线的边缘都做了模糊化处理,只为了让人眼看起来比较舒服,但在科学或医学领域应该不能允许多余的像素。

下面的代码可以直接复制到本地一个html文件中,然后用IE9/Opera10/etc.打开。至于其中用到的512*512尺寸的CT、SMPTE和戴帽子女孩的图片,读者可以在网上自行下载。其中那个著名的戴帽子女孩,用“灰度图象”作为关键字就能找到。

HTML5灰度图像处理练习1:直方图和灰度反转

HTML5灰度图像处理练习1:直方图和灰度反转

HTML5灰度图像处理练习1:直方图和灰度反转

<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>Grayscale Image Test</title> <style type="text/css"> table {margin:auto;} </style> </head> <body style="background-color: #eeeeee;" mce_style="background-color: #eeeeee;"> <table> <tr align="center"><td colspan="2"><h3>Grayscale Image Test</h3><hr height="1px"/></td> </tr> <tr> <td align="right"> <button id="invertImage" onclick="invertImage();return true;">Invert</button> <button id="invertImage" onclick="loadImage(girlUri);return true;">Reset</button> <button id="smpteImage" onclick="loadImage(smpteUri);return true;">SMPTE</button> <button id="ctImage" onclick="loadImage(ctUri);return true;">CT</button> </td> <td> </td> </tr> <tr align="center"> <td><canvas id="imageviewer" width="512px" height="512px" style="border: 1px solid;" mce_style="border: 1px solid;" /></td> <td><canvas id="statistic" width="256" height="512px" style="border: 1px solid;" mce_style="border: 1px solid;" /></td> </tr> <tr align="center"><td colspan="2">© May, 2011, [email protected]</td> </tr> </table> </body> <script> var ctUri = 'ct.jpg'; var smpteUri = 'smpte.gif'; var girlUri = 'dmtjc5016.gif'; var icanvas = document.getElementById('imageviewer'); var icanvasWidth = parseInt(icanvas.getAttribute("width")); var icanvasHeight = parseInt(icanvas.getAttribute("height")); var icontext = icanvas.getContext('2d'); var scanvas = document.getElementById('statistic'); var scanvasWidth = parseInt(scanvas.getAttribute("width")); var scanvasHeight = parseInt(scanvas.getAttribute("height")); var scontext = scanvas.getContext('2d'); function loadImage(uri){ var img = new Image(); img.src = uri; img.onload = function(){ icontext.drawImage(img,0,0); loadStatistic(); }; } function loadStatistic(){ var imgData = icontext.getImageData(0,0,icanvasWidth,icanvasHeight); var pixTotal = imgData.height*imgData.width; var pixCount = []; for(i=0;i<256;i++) pixCount[i]=0; for(y=0;y<imgData.height;y++){ for(x=0;x<imgData.width;x++){ var pv = Math.min(255,imgData.data[(y*imgData.width+x)*4]); pixCount[pv]++; } } scontext.clearRect(0,0,scanvasWidth,scanvasHeight); var stImg = scontext.getImageData(0,0,scanvasWidth,scanvasHeight); for(x=0;x<256;x++){ var c = pixCount[x]; var h = stImg.height - Math.round(stImg.height*c/pixTotal); for(y=h;y<stImg.height;y++){ var i = (y*stImg.width+x)*4; stImg.data[i]=stImg.data[i+1]=stImg.data[i+2]=0; stImg.data[i+3]=255; } } scontext.putImageData(stImg,0,0); } function invertImage(){ var imgData = icontext.getImageData(0,0,icanvasWidth,icanvasHeight); for(y=0;y<imgData.height;y++){ for(x=0;x<imgData.width;x++){ var i = (y*imgData.width+x)*4; var pv = Math.abs(255-imgData.data[i]); imgData.data[i]=imgData.data[i+1]=imgData.data[i+2]=pv; } } icontext.putImageData(imgData,0,0); loadStatistic(); } window.addEventListener("load", loadImage(girlUri), true); </script> <html>