我正在尝试理解并在我的灰度和彩色图像上应用CLAHE。我还在第478页找到this book,这有助于用一些C ++代码和this tutorial解释CLAHE。
我对GLSL很新,无法用它来解决问题。任何人都可以帮我在OpenGL / WebGL中做到这一点吗?另外,我不允许使用OpenCV库。
修改 This link更全面。
偶数this是自适应直方图的另一个完美解决方案,但我需要通过更改直方图的能力来获得图像。
编辑2: 不知怎的,我能够让CLAHE在canvas 2d上工作,显然使用CPU,指的是这可以让任何人知道如何在GPU中做同样的事情?
这是fiddle
代码: `
var iml = document.getElementById('imageLoader');
iml.addEventListener('change', handleImage, false);
var cnv = document.getElementById('imageCanvas');
var ctx = cnv.getContext('2d');
var cnvori = document.getElementById('imageOriginalCanvas')
var ctxori = cnvori.getContext('2d');
function handleImage(e){
var reader = new FileReader();
reader.onload = function(event){
var img = new Image;
img.onload = function(){
cnvori.width = cnv.width = img.width;
cnvori.height = cnv.height = img.height;
ctx.drawImage(img,0,0,img.width,img.height);
ctxori.drawImage(img,0,0,img.width,img.height);
var imgData = ctx.getImageData(0,0,img.width,img.height);
var min=255, max=0;
var intens=[];
var levels=[];
var j=0;
for (var i=0;i<imgData.data.length;i+=4) {
intens[j] = (imgData.data[i]+imgData.data[i+1]+imgData.data[i+2] )/3;
j++;
}
var tilesize = [32, 32];
var clipLimit = 0.1;
// number of bins
var num_bins = 256;
var h = img.height;
var w = img.width;
// number of tiles in x and y direction
var xtiles = Math.ceil(w / tilesize[0]);
var ytiles = Math.ceil(h / tilesize[1]);
var cdfs = new Array(ytiles);
for(var i=0;i<ytiles;i++)
cdfs[i] = new Array(xtiles);
var inv_tile_size = [1.0 / tilesize[0], 1.0 / tilesize[1]];
var cdf = [];
// create histograms
for(var i=0;i<ytiles;i++){
var y0 = i * tilesize[1];
var y1 = y0 + tilesize[1];
for(var j=0;j<xtiles;j++)
{
var x0 = j * tilesize[0];
var x1 = x0 + tilesize[0];
var hist = histogram(intens, x0, y0, x1, y1, num_bins, h, w);
cdfs[i][j] = buildcdf(hist, num_bins, tilesize[0] * tilesize[1], clipLimit);
}
}
var finalArray = [];
var p = 0;
for(var y=0, idx=0;y<h;++y){
for(var x=0;x<w;++x, idx+=4){
// intensity of current pixel
var I = Math.floor(intens[y*w+x]);
var tx = x * inv_tile_size[0] - 0.5;
var ty = y * inv_tile_size[1] - 0.5;
var xl = Math.max(Math.floor(tx), 0);
var xr = Math.min(xl+1, xtiles-1);
var yt = Math.max(Math.floor(ty), 0);
var yd = Math.min(yt+1, ytiles-1);
var fx = tx - xl;
var fy = ty - yt;
var cdf11 = (cdfs[yt][xl][I]) * 255 ;
var cdf12 = (cdfs[yd][xl][I]) * 255;
var cdf21 = (cdfs[yt][xr][I]) * 255;
var cdf22 = (cdfs[yd][xr][I]) * 255;
var Iout = (1 - fx) * (1 - fy) * cdf11
+ (1 - fx) * fy * cdf12
+ fx * (1 - fy) * cdf21
+ fx * fy * cdf22;
finalArray[p] = Iout;
p++;
}
}
var pixelLength = h * w;
for (var index = 0, indexToFill = 3; index < pixelLength; index++, indexToFill = indexToFill + 4) {
var result = finalArray[index];
imgData.data[indexToFill-3] = 0;
imgData.data[indexToFill-2] = 0;
imgData.data[indexToFill-1] = 0;
imgData.data[indexToFill] = 255 - result;
}
ctx.putImageData(imgData,0,0);
}
img.src = event.target.result;
}
reader.readAsDataURL(e.target.files[0]);
}
var getInputArray = function(mArray, x, y, hDiff, vDiff, rows, columns){
var inputArray = [];
var k = 0;
for(var i=x-vDiff;i<=x+vDiff;i++){
for(var j=y-hDiff;j<=y+hDiff;j++){
if(i>=0 && j>=0 && i<rows && j<columns){
inputArray[k] = mArray[i][j];
}else{
inputArray[k] = 0;
}
k++;
}
}
var finalResult = getHEArray(inputArray, x, y, mArray);
return finalResult;
}
// build cdf from given pdf
function buildcdf(hist, num_bins, num_pixels, clipLimit){
var excess = 0;
for(var i=0;i<num_bins;++i){
hist[i] = hist[i] / num_pixels;
if(hist[i]>clipLimit){
excess = excess + hist[i] - clipLimit;
hist[i] = clipLimit;
}
}
var addExcess = excess/num_bins;
var cumuhist = [];
cumuhist[0] = hist[0] + addExcess;
for(var i=1;i<num_bins;++i)
cumuhist[i] = cumuhist[i-1] + hist[i] + addExcess;
return cumuhist;
}
function histogram(intens, x1, y1, x2, y2, num_bins, h, w){
var hist = [];
for(var i=0;i<num_bins;++i)
hist[i] = 0;
for(var y=y1;y<y2;++y){
for(var x=x1;x<x2;++x){
var idx;
if(x>=w && y<h){
idx = (y * w + (w - 1));
}else if(y>=h && x<w){
idx = ((h-1) * w + x);
}else if(y>=h && x>=w){
idx = (h * w) - 1;
}else{
idx = (y * w + x);
}
var val = Math.floor(intens[idx]);
hist[val]++;
}
}
return hist;
}
`