Nadesłany przez Tomasz Lubiński, 18 lutego 2013 22:28
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.Pobierz pełne rozwiązanie.
Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.
retinex.js:
//Retinex //(c) 2013 by Tomasz Lubinski //www.algorytm.org /* Data of the image */ var imageData; /* Papers: "Recursive Implementation of the gaussian filter.", Ian T. Young , Lucas J. Van Vliet, Signal Processing 44, Elsevier 1995. */ function gaussian_coefs(sigma) { var result = new Array(); var q = 0; if (sigma >= 2.5) q = 0.98711 * sigma - 0.96330; else if ((sigma >= 0.5) && (sigma < 2.5)) q = 3.97156 - 4.14554 * Math.sqrt(1.0 - 0.26891 * sigma); else q = 0.1147705018520355224609375; var q2 = q * q; var q3 = q * q2; result.push(1.57825+(2.44413*q)+(1.4281 *q2)+(0.422205*q3)); result.push( (2.44413*q)+(2.85619*q2)+(1.26661 *q3)); result.push( -((1.4281*q2)+(1.26661 *q3))); result.push( (0.422205*q3)); result.push(1.0-((result[1]+result[2]+result[3])/result[0])); return result; } function gausssmooth(imgIn, imgOut, shift, rowstride, size, coefs) { // forward pass var w1 = new Array(); var w2 = new Array(); w1[0] = imgIn[shift]; w1[1] = imgIn[shift]; w1[2] = imgIn[shift]; for(var i=0, n=3; i<size; i++, n++) { w1[n] = (coefs[4]*imgIn[shift+i*rowstride] + ((coefs[1]*w1[n-1] + coefs[2]*w1[n-2] + coefs[3]*w1[n-3] ) / coefs[0])); } w1[size+0] = w1[size-1]; w1[size+1] = w1[size-2]; w1[size+2] = w1[size-3]; // backward pass w2[size+0]= w1[size+0]; w2[size+1]= w1[size+1]; w2[size+2]= w1[size+2]; w2[size+3]= w1[size+2]; w2[size+4]= w1[size+2]; w2[size+5]= w1[size+2]; for(var i=size-1, n=i+3; i>=0; i--, n--) { w2[n] = imgOut[shift+i*rowstride] = (coefs[4]*w1[n] + ((coefs[1]*w2[n+1] + coefs[2]*w2[n+2] + coefs[3]*w2[n+3] ) / coefs[0])); } } /* Retinex */ function retinex(sigmas, weights, alfa, beta) { var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); //read the width and height of the canvas var width = canvas.width; var height = canvas.height; var bluredImageData = ctx.createImageData(width, height).data; var imageDataData = imageData.data; //initialize result var retinexResult = new Array(); //for each channel (R, G, B) retinexResult[0] = new Array(); retinexResult[1] = new Array(); retinexResult[2] = new Array(); //for each line for (var i=0; i<height; i++) { retinexResult[0][i] = new Array(); retinexResult[1][i] = new Array(); retinexResult[2][i] = new Array(); for (var j=0; j<width; j++) { retinexResult[0][i][j] = 0; retinexResult[1][i][j] = 0; retinexResult[2][i][j] = 0; } } //for all requested scales (MSR - multi scale retinex) for (var s=0; s<sigmas.length; s++) { //gaussian blur coefs var coefs = gaussian_coefs(sigmas[s]) //Gaussian blur horizontal for (var i=0; i<height; i++) { gausssmooth(imageDataData, bluredImageData, i*width*4+0, 4, width, coefs); gausssmooth(imageDataData, bluredImageData, i*width*4+1, 4, width, coefs); gausssmooth(imageDataData, bluredImageData, i*width*4+2, 4, width, coefs); } //Gaussian blur vertical for (var i=0; i<width; i++) { gausssmooth(bluredImageData, bluredImageData, i*4+0, 4*width, height, coefs); gausssmooth(bluredImageData, bluredImageData, i*4+1, 4*width, height, coefs); gausssmooth(bluredImageData, bluredImageData, i*4+2, 4*width, height, coefs); } //Retinex (SSR - single scale retinex) for (var i=0; i<height; i++) { for (var j=0; j<width; j++) { var index = (i*width+j)*4; retinexResult[0][i][j] += weights[s] * Math.log((imageDataData[index+0] + 1.0) / (bluredImageData[index+0] + 1.0)); retinexResult[1][i][j] += weights[s] * Math.log((imageDataData[index+1] + 1.0) / (bluredImageData[index+1] + 1.0)); retinexResult[2][i][j] += weights[s] * Math.log((imageDataData[index+2] + 1.0) / (bluredImageData[index+2] + 1.0)); } } } //Normalize result var min = retinexResult[0][0][0]; var max = min; for (var i=0; i<height; i++) { for (var j=0; j<width; j++) { if (min > retinexResult[0][i][j]) min = retinexResult[0][i][j]; else if (max < retinexResult[0][i][j]) max = retinexResult[0][i][j]; if (min > retinexResult[1][i][j]) min = retinexResult[1][i][j]; else if (max < retinexResult[1][i][j]) max = retinexResult[1][i][j]; if (min > retinexResult[2][i][j]) min = retinexResult[2][i][j]; else if (max < retinexResult[2][i][j]) max = retinexResult[2][i][j]; } } //Put result to the new image var newImageData = ctx.createImageData(width, height); var newImageDataData = newImageData.data; var range = (max - min) / 255.0; for (var i=0; i<height; i++) { for (var j=0; j<width; j++) { //color restoration (MSRCR - multiscale retinex with color restoration) var index = (i*width+j)*4; var sum = imageDataData[index+0] + imageDataData[index+1] + imageDataData[index+2] + 3.0; value = retinexResult[0][i][j] * beta*Math.log(alfa*(imageDataData[index+0] + 1.0) / sum); value = (value - min) / range; if (value > 255) newImageDataData[index+0] = 255; else if (value < 0) newImageDataData[index+0] = 0; else newImageDataData[index+0] = value; value = retinexResult[1][i][j] * beta*Math.log(alfa*(imageDataData[index+1] + 1.0) / sum); value = (value - min) / range; if (value > 255) newImageDataData[index+1] = 255; else if (value < 0) newImageDataData[index+1] = 0; else newImageDataData[index+1] = value; value = retinexResult[2][i][j] * beta*Math.log(alfa*(imageDataData[index+2] + 1.0) / sum); value = (value - min) / range; if (value > 255) newImageDataData[index+2] = 255; else if (value < 0) newImageDataData[index+2] = 0; else newImageDataData[index+2] = value; } } //set as no trasparent for (var i=0; i<height; i++) { for (var j=0; j<width; j++) { var index = (i*width+j)*4; newImageDataData[index+3] = 255; } } // copy the image data back onto the canvas ctx.putImageData(newImageData, 0, 0); } /* load image pointed by param_file to canvas */ function loadImage(imgSrc) { var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); // add file:// if user specified local path if (imgSrc.indexOf("//") == -1 && imgSrc.indexOf(".") != 0) { imgSrc = "file:///" + imgSrc; } // load file into canvas var img = new Image(); img.onload = function(){ var width = img.width; var height = img.height; canvas.width = width; canvas.height = height; ctx.drawImage(img,0,0); // replace transparent with white try { imageData = ctx.getImageData(0, 0, width, height); } catch(e) { netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); imageData = ctx.getImageData(0, 0, width, height); } for (var i=0; i<height; i++) { for (var j=0; j<width; j++) { index = (i*width+j)*4; if (imageData.data[index+3] == 0) { imageData.data[index+3] = 255; imageData.data[index+0] = 255; imageData.data[index+1] = 255; imageData.data[index+2] = 255; } } } } img.src = imgSrc; }