How can I access imageData from a renderTarget? - javascript

I'm a university masters degree student in Computer Graphics, I'm having difficulty using three.js to access the image data(pixels) of a texture created with a EffectComposer.
The first composer (composer) is using a line detection shader to find road lines in a lane, and put the result in a renderTarget (rt_Binary). My second composer (fcomposer2) uses a shader that paints an area green if is within a certain space.
The plan was to render the composer first and after analysing the rt_Binary image i could determine the limits.
I found some functions that allow me to get the imagedata (getImageData(image) and getPixel(imagedata, x, y)) but they only work on these occasions:
// before image
var imagedata = getImageData(videoTexture.image);
// processed image
var imagedata2 = getImageData(renderer.domElement);
If a put the first composer to render to screen, i get the correct values for the limits, but when i put the second composer, i get the wrong values for the limits.
Is there any way to get the imageData from a renderTarget? is so, how?
Edit1:
Here's the code for script that i use for the html:
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<title>Tests WebGL</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="three.js/build/three.js"></script>
<script src="js/CopyShader.js"></script>
<script src="js/EffectComposer.js"></script>
<script src="js/MaskPass.js" ></script>
<script src="js/RenderPass.js" ></script>
<script src="js/ShaderPass.js"></script>
<script src="js/stats.min.js" ></script>
<!-- Shaders -->
<script src="js/shaders/KernelShader.js" ></script>
<script src="js/shaders/SimpleShader.js"></script>
<script src="js/shaders/MyShader.js"></script>
<script src="js/shaders/BinaryShader.js"></script>
<script type="text/javascript">
var scene, fscene, sceneF;
var camera;
var renderer, rt_Binary;
var composer;
var stats;
var fmaterial;
var videoTexture;
var videoWidth = 480;
var videoHeight = 270;
var rendererWidth = videoWidth;
var rendererHeight = videoHeight;
var x_max = 345;//videoWidth*0.72; //
var x_min = 120;//videoWidth*0.25; //
var y_max = 189;//videoHeight*0.7 ;
var y_min = 148;//videoHeight*0.55;
// var ml=0.0, mr=0.0, mm=0.0;
// var bl=0.0, br=0.0, bm=0.0;
var yMaxL = 0, yMinL = 0, yMaxR = 0, yMinR = 0;
var xMaxL = 0, xMinL = 0, xMaxR = 0, xMinR = 0;
var frame = 0;
// init the scene
window.onload = function() {
renderer = new THREE.WebGLRenderer(
{
antialias: true, // to get smoother output
preserveDrawingBuffer: true // to allow screenshot
});
renderer.setClearColor(0xffffff, 1);
renderer.autoClear = false;
renderer.setSize(rendererWidth, rendererHeight);
document.getElementById('container').appendChild(renderer.domElement);
//add stats
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
document.getElementById('container').appendChild(stats.domElement);
// create Main scene
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(35, rendererWidth / rendererHeight, 1, 10000);
camera.position.set(0, 1, 6);
scene.add(camera);
// define video element
video = document.createElement('video');
// video.src = 'GOPR0007.webm';
video.src = 'output.webm';
video.width = videoWidth;
video.height = videoHeight;
video.autoplay = true;
video.loop = true;
//create 3d object and apply video texture to it
var videoMesh = new THREE.Object3D();
scene.add(videoMesh);
videoTexture = new THREE.Texture(video);
var geom = new THREE.PlaneGeometry(1, 1);
material = new THREE.MeshBasicMaterial({map: videoTexture});
var mesh = new THREE.Mesh(geom, material);
videoMesh.add(mesh);
var renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBufer: false };
rt_Binary = new THREE.WebGLRenderTarget( videoWidth, videoHeight, renderTargetParameters );
// Composers
// composer = new THREE.EffectComposer(renderer, renderTarget2);
composer = new THREE.EffectComposer(renderer, rt_Binary );
composer.addPass(new THREE.RenderPass(scene, camera));
var simple = new SimpleShader.Class(videoWidth, videoHeight);
var simEffect = new THREE.ShaderPass(simple.shader);
composer.addPass(simEffect);
var ef = new BinaryShader.Class(videoWidth, videoHeight, 1.1, [-2,-2,-2,0,0,0,2,2,2]);
var effect = new THREE.ShaderPass(ef.shader);
composer.addPass(effect);
var copyPass = new THREE.ShaderPass(THREE.CopyShader);
// copyPass.renderToScreen = true;
composer.addPass(copyPass);
//New scene
sceneF = new THREE.Scene();
sceneF.add(camera);
var videoMesh2 = new THREE.Object3D();
sceneF.add(videoMesh2);
var geomF = new THREE.PlaneGeometry(1, 1);
var materialF = new THREE.MeshBasicMaterial({map: videoTexture});
var meshF = new THREE.Mesh(geomF, materialF);
sceneF.add(meshF);
fcomposer2 = new THREE.EffectComposer(renderer );
fcomposer2.addPass(new THREE.RenderPass(sceneF, camera));
fcomposer2.addPass(simEffect);
var ef1 = new MyShader.Class(videoWidth, videoHeight, [yMaxL,yMinL,xMaxL,xMinL,yMaxR,yMinR,xMaxR,xMinR], videoTexture);
var effect1 = new THREE.ShaderPass(ef1.shader);
fcomposer2.addPass(effect1);
var copyPass2 = new THREE.ShaderPass(THREE.CopyShader);
copyPass2.renderToScreen = true;
fcomposer2.addPass(copyPass2);
animate();
}
// animation loop
function animate() {
// loop on request animation loop
// - it has to be at the begining of the function
requestAnimationFrame(animate);
// do the render
render();
stats.update();
if ((frame % 50) == 0) {
console.log("frame ", frame, " ");
console.log("yMaxL: ", yMaxL, " ");
console.log("yMinL: ", yMinL, " ");
console.log("xMaxL: ", xMaxL, " ");
console.log("xMinL: ", xMinL, " ");
console.log("yMaxR: ", yMaxR, " ");
console.log("yMinR: ", yMinR, " ");
console.log("xMaxR: ", xMaxR, " ");
console.log("xMinR: ", xMinR, " ");
manipulatePixels();
}
frame = frame + 1;
yMaxL = 0, yMinL = 0, yMaxR = 0, yMinR = 0;
xMaxL = 0, xMinL = 0, xMaxR = 0, xMinR = 0;
}
// render the scene
function render() {
if (video.readyState === video.HAVE_ENOUGH_DATA) {
videoTexture.needsUpdate = true;
}
// actually render the scene
renderer.clear();
composer.render();
var left_x = new Array();
var left_y = new Array();
var l = 0;
var right_x = new Array();
var right_y = new Array();
var r = 0;
if (frame == 200) {
var imagedata2 = getImageData(renderer.domElement);
var middle = imagedata2.width / 2;
for (var x=x_min; x < x_max; x=x+1) {
for (var y=y_min; y < y_max; y=y+1) {
var pixel = getPixel(imagedata2, x, y);
if (pixel.g > 0)
{
//console.log(pixel);
if (x < middle) {
left_x[l] = x;
left_y[l] = y;
l++;
}
else {
right_x[r] = x;
right_y[r] = y;
r++;
}
}
}
}
lineEquation(left_x, left_y, right_x, right_y);
}
fcomposer2.render();
}
function lineEquation(left_x,left_y,right_x,right_y) {
var newYMAX = left_y[0];
var newYMIN = left_y[0];
var maximosL = new Array();
var minimosL = new Array();
//left
for (var i=1; i < left_y.length; i++) {
if (left_y[i]>newYMAX) newYMAX = left_y[i];
else {
if (left_y[i]<newYMIN) newYMIN = left_y[i];
}
}
yMaxL = newYMAX;
yMinL = newYMIN;
// yMaxL = ymaxL/videoHeight;
// yMinL = yminL/videoHeight;
var pmin=0, pmax=0;
for (var i=0; i < left_y.length; i++) {
if (left_y[i] === newYMAX) {
// console.log(left_y[i]);
// console.log(left_x[i]);
maximosL[pmax] = left_x[i];
pmax++;
}
}
for (var j=0; j < left_y.length; j++) {
if (left_y[j] === newYMIN) {
// console.log(left_y[j]);
// console.log(left_x[j]);
minimosL[pmin] = left_x[j];
pmin++;
}
}
// console.log(maximosL);
// console.log(minimosL);
var sumMAX = 0, sumMIN = 0;
for (var i=0; i< maximosL.length; i++) {
sumMAX = sumMAX + maximosL[i];
}
for (var j=0; j< minimosL.length; j++) {
sumMIN = sumMIN + minimosL[j];
}
xMaxL = sumMAX/maximosL.length;
xMinL = sumMIN/minimosL.length;
// xMaxL /= videoWidth;
// xMinL /= videoWidth;
//right
var maximosR = new Array();
var minimosR = new Array();
newYMAX = right_y[0];
newYMIN = right_y[0];
pmin=0; pmax=0;
for (var i=0; i < right_y.length; i++) {
if (right_y[i]> newYMAX) newYMAX = right_y[i];
else {
if (right_y[i]< newYMIN) newYMIN = right_y[i];
}
}
yMaxR = newYMAX;
yMinR = newYMIN;
// yMaxR = ymaxR/videoHeight;
// yMinR = yminR/videoHeight;
for (var i=0; i < right_y.length; i++) {
if (right_y[i] === newYMAX)
{maximosR[pmax] = right_x[i]; pmax++;}
if (right_y[i] === newYMIN)
{minimosR[pmin] = right_x[i]; pmin++;}
}
// console.log(maximosR);
// console.log(minimosR);
xMaxR=0;
for (var i=0; i< maximosR.length; i++) {
xMaxR += maximosR[i];
}
xMinR=0;
for (var i=0; i< minimosR.length; i++) {
xMinR += minimosR[i];
}
// console.log(xMaxR);
// console.log(xMinR);
xMaxR /= maximosR.length;
xMinR /= minimosR.length;
// console.log(xMaxR);
// console.log(xMinR);
// xMinR /= videoWidth;
// xMaxR /= videoWidth;
}
function manipulatePixels() {
// imagem antes
var imagedata = getImageData(videoTexture.image);
// imagem processada
var imagedata2 = getImageData(renderer.domElement);
// console.log(getPixel(imagedata, 480 - 1, 270 - 1));
// console.log(getPixel(imagedata2, 480 - 1, 270 - 1));
}
function getImageData(image) {
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext('2d');
context.drawImage(image, 0, 0);
return context.getImageData(0, 0, image.width, image.height);
}
function getPixel(imagedata, x, y) {
var position = (x + imagedata.width * y) * 4, data = imagedata.data;
return {r: data[ position ], g: data[ position + 1 ], b: data[ position + 2 ], a: data[ position + 3 ]};
}
function findLineByLeastSquares(values_x, values_y) {
var sum_x = 0;
var sum_y = 0;
var sum_xy = 0;
var sum_xx = 0;
/*
* We'll use those variables for faster read/write access.
*/
var x = 0;
var y = 0;
var values_length = values_x.length;
if (values_length != values_y.length) {
throw new Error('The parameters values_x and values_y need to have same size!');
}
/*
* Nothing to do.
*/
if (values_length === 0) {
return [ [], [] ];
}
/*
* Calculate the sum for each of the parts necessary.
*/
for (var v = 0; v < values_length; v++) {
x = values_x[v];
y = values_y[v];
sum_x += x;
sum_y += y;
sum_xx += (x*x);
sum_xy += (x*y);
}
console.log (sum_x);
console.log(sum_y);
console.log(sum_xx);
console.log(sum_xy);
console.log(values_length);
/*
* Calculate m and b for the formular:
* y = x * m + b
*/
var m = (sum_x*sum_y - values_length*sum_xy) / (sum_x*sum_x - values_length*sum_xx);
var b = (sum_y - (m*sum_x))/values_length;
//console.log([m,b]);
return [m, b];
}
//resize method
/**window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
} */
</script>
Edit2 : Some images of what i'm trying to do: Image 1 shows the results from composer on the console, the limits i get from the lineEquation function are the correct ones for what i intend to do, but in Image 2 shows the results from fcomposer2 (fixed area) and on the console, the limits are the wrong ones.
![Image1]: http://prntscr.com/1ays73
![Image2]: http://prntscr.com/1ays0j
Edit3 :
By "access" i mean to be able to read the values of the pixels from the texture created by the binaryShader.
For example, in image1 the lines are painted in blue/green tone, I wanted to search the position of the pixels (x,y) in the image that the renderTarget would save. If i could find those pixels, i could adapt the green area in image2 to fit between the road lines.
This processing is need to make the green area overlap the current driving lane the user is currently on, if i can't get those points, i can't identify a lane.

I got it to work. Apparently i forgot to declare the fcomposer2 in the beginning of the script.
Thanks for the responses/comments, and sorry for the inconvenience.

Related

How to run u2net model with ONNX in browser (client side)?

I am trying to run u2net model in browser, I have converted the pytorch u2netp model into ONNX model and wrote the following code to run it but the results very poor. I followed the same preprocessing steps as that of python script but did not get the results. I was not able to find onnx functions to perform the preprocessing so I have used for loops to change the values in each channel.
<!DOCTYPE html>
<html>
<header>
<title>ONNX Runtime JavaScript examples: Quick Start - Web (using script tag)</title>
<input id="image-selector" type="file" style="top:10px;left:10px" >
<button id="predict-button" class="btn btn-dark float-right" style="top:10px;left:70px" >Predict</button>
<img id="selected-image" src="" />
<canvas id="canvas" width =320px height=320px ></canvas>
</header>
<body>
<!-- import ONNXRuntime Web from CDN -->
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.min.js"></script>
<script>
$("#image-selector").change(function () {
let reader = new FileReader();
reader.onload = function () {
let dataURL = reader.result;
$("#selected-image").attr("src", dataURL);
}
let file = $("#image-selector").prop("files")[0];
reader.readAsDataURL(file);
});
$("#predict-button").click(async function (){
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const session = await ort.InferenceSession.create('./u2netp.onnx').then(console.log("model loaded"));
const inputNames = session.inputNames;
const outputNames = session.outputNames;
console.log('inputNames', inputNames)
console.log('outputNames', outputNames)
let image = $("#selected-image").get(0);
console.log("image.naturalHeight", image.naturalHeight)
console.log("image.naturalWidth", image.naturalWidth)
var oc = document.createElement('canvas'),
octx = oc.getContext('2d');
oc.width = 320;
oc.height = 320;
octx.drawImage(image, 0, 0, oc.width, oc.height);
var input_imageData = octx.getImageData(0, 0, 320, 320);
var floatArr = new Float32Array(320 * 320 * 3)
var j = 0
for (let i = 1; i < input_imageData.data.length+1; i ++) {
if(i % 4 != 0){
floatArr[j] = (input_imageData.data[i-1].toFixed(2))/255; // red color
j = j + 1;
}
}
console.log("floatArr1", floatArr)
for (let i = 1; i < floatArr.length+1; i += 3) {
floatArr[i-1] = (floatArr[i-1] - 0.485)/0.229 // red color
floatArr[i] = (floatArr[i] - 0.456)/0.224 // green color
floatArr[i+1] = (floatArr[i+1] - 0.406)/0.225 // blue color
}
console.log("floatArr2", floatArr)
const input = new ort.Tensor('float32', floatArr, [1, 3, 320, 320])
a = inputNames[0]
console.log("a", a)
const feeds = {"input.1": input};
console.log("feeds", feeds)
const results = await session.run(feeds).then();
const pred = Object.values(results)[0]
console.log('pred', pred)
console.log('pred.data.length', pred.data.length)
console.log('pred.data[0]', Math.round(pred.data[0]*255))
var myImageData = ctx.createImageData(320, 320);
for (let i = 0; i < pred.data.length*4; i += 4) {
var pixelIndex = i;
if(i != 0){
t = i/4;
}
else{
t = 0;
}
myImageData.data[pixelIndex ] = Math.round(pred.data[t]*255); // red color
myImageData.data[pixelIndex + 1] = Math.round(pred.data[t]*255); // green color
myImageData.data[pixelIndex + 2] = Math.round(pred.data[t]*255); // blue color
myImageData.data[pixelIndex + 3] = 255;
}
ctx.putImageData(myImageData, 10, 10);
console.log("myImageData", myImageData)
});
</script>
</body>
</html>
Needed to transpose the image data array before passing it to the model.
<!DOCTYPE html>
<html>
<header>
<title>ONNX Runtime JavaScript examples: Quick Start - Web (using script tag)</title>
<input id="image-selector" type="file" style="top:10px;left:10px" >
<button id="predict-button" class="btn btn-dark float-right" style="top:10px;left:70px" >Predict</button>
<img id="selected-image" src="" />
<canvas id="canvas" width =320px height=320px ></canvas>
</header>
<body>
<!-- import ONNXRuntime Web from CDN -->
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.min.js"></script>
<script>
$("#image-selector").change(function () {
let reader = new FileReader();
reader.onload = function () {
let dataURL = reader.result;
$("#selected-image").attr("src", dataURL);
}
let file = $("#image-selector").prop("files")[0];
reader.readAsDataURL(file);
});
// async function main() {
$("#predict-button").click(async function (){
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const session = await ort.InferenceSession.create('./u2netp.onnx').then(console.log("model loaded"));
// input_name = getInputs();
const inputNames = session.inputNames;
const outputNames = session.outputNames;
let image = $("#selected-image").get(0);
var oc = document.createElement('canvas'),
octx = oc.getContext('2d');
oc.width = 320;
oc.height = 320;
octx.drawImage(image, 0, 0, oc.width, oc.height);
var input_imageData = octx.getImageData(0, 0, 320, 320);
console.log("input_imageData",input_imageData.data)
var floatArr = new Float32Array(320 * 320 * 3)
var floatArr1 = new Float32Array(320 * 320 * 3)
var floatArr2 = new Float32Array(320 * 320 * 3)
var j = 0
for (let i = 1; i < input_imageData.data.length+1; i ++) {
if(i % 4 != 0){
floatArr[j] = (input_imageData.data[i-1].toFixed(2))/255; // red color
j = j + 1;
}
}
console.log("floatArr", floatArr)
for (let i = 1; i < floatArr.length+1; i += 3) {
floatArr1[i-1] = (floatArr[i-1] - 0.485)/0.229 // red color
floatArr1[i] = (floatArr[i] - 0.456)/0.224 // green color
floatArr1[i+1] = (floatArr[i+1] - 0.406)/0.225 // blue color
}
var k = 0
for (let i = 0; i < floatArr.length; i += 3) {
floatArr2[k] = floatArr[i] // red color
k = k + 1
}
console.log("k", k)
var l = 102400
for (let i = 1; i < floatArr.length; i += 3) {
floatArr2[l] = floatArr[i] // red color
l = l + 1
}
console.log("l", l)
var m = 204800
for (let i = 2; i < floatArr.length; i += 3) {
floatArr2[m] = floatArr[i] // red color
m = m + 1
}
const input = new ort.Tensor('float32', floatArr2, [1, 3, 320, 320])
a = inputNames[0]
const feeds = {"input.1": input};
const results = await session.run(feeds).then();
const pred = Object.values(results)[0]
var myImageData = ctx.createImageData(320, 320);
for (let i = 0; i < pred.data.length*4; i += 4) {
var pixelIndex = i;
if(i != 0){
t = i/4;
}
else{
t = 0;
}
myImageData.data[pixelIndex ] = Math.round(pred.data[t]*255); // red color
myImageData.data[pixelIndex + 1] = Math.round(pred.data[t]*255); // green color
myImageData.data[pixelIndex + 2] = Math.round(pred.data[t]*255); // blue color
myImageData.data[pixelIndex + 3] = 255;
}
ctx.putImageData(myImageData, 10, 10);
});
</script>
</body>
</html>

Adding duplicate tiles from different arrays PIXI.js

I'm trying to create a slot game;
I have some images that I put into an array
var createSlots = function(){
//setup images as tilingSprites
var slot1 = new PIXI.extras.TilingSprite(t1, 200, 200);
var slot2 = new PIXI.extras.TilingSprite(t2, 200, 200);
var slot3 = new PIXI.extras.TilingSprite(t3, 200, 200);
var slot4 = new PIXI.extras.TilingSprite(t4, 200, 200);
var slot5 = new PIXI.extras.TilingSprite(t5, 200, 200);
var slot6 = new PIXI.extras.TilingSprite(t6, 200, 200);
var slot7 = new PIXI.extras.TilingSprite(t7, 200, 200);
var slot8 = new PIXI.extras.TilingSprite(t8, 200, 200);
var slot9 = new PIXI.extras.TilingSprite(t9, 200, 200);
var slot10 = new PIXI.extras.TilingSprite(t10, 200, 200);
//push slots into array; images, sprites etc.
mainSlotArr.push(slot1, slot2, slot3, slot4, slot5, slot6, slot7, slot8, slot9, slot10);
};
for the moment I have 2 functions (will combine them once I get this working)
createReels1 and createReels2
what they do is copy the mainSlotArray use a shuffle function
Then populate to 2 columns (reels) each (at the moment createReels2 only does one reel)
it then removes the array element from the array it's using
The trouble I'm having is that whatever image tiles are used in createReels2, disappear if they are being used in createReels1 function, e.g if image1.png used in createReels2 and createReels1, then it is not visible in the first 2 reels
createReels functions below (alot of hard coding!)
var createReels1 = function(){
slotArr1 = mainSlotArr.slice();
shuffle(slotArr1);
var counter = 0;
var num = 0
for(var i = 0; i <2; i++){
var slotContainer = new PIXI.Container();
slotContainer.width = 100;
slotContainer.height = 400;
slotContainer.y = 100;
slotContainer.x = i*130;
stage.addChild(slotContainer);
slotContainerArr.push(slotContainer);
for(var j = 0; j < 3; j++){
var slot = slotArr1[j];
var toDel = slotArr1.indexOf(slot);
slot.scale.y = slot.scale.x = .5;
console.log(slot);
var nextY = j*(slot.height/2);
slot.y = nextY;
slotContainerArr[i].addChild(slot);
slotArr1.splice(toDel, 1);//remove from array
}
}
}
var createReels2 = function(){
slotArr2 = mainSlotArr.slice();
shuffle(slotArr2);
var counter = 0;
var num = 0
for(var i = 0; i <1; i++){
var slotContainer = new PIXI.Container();
slotContainer.width = 100;
slotContainer.height = 400;
slotContainer.y = 100;
slotContainer.x = 260;
stage.addChild(slotContainer);
slotContainerArr.push(slotContainer);
for(var j = 0; j < 3; j++){
var slot = slotArr2[j];
var toDel = slotArr2.indexOf(slot);
slot.scale.y = slot.scale.x = .5;
var nextY = j*(slot.height/2);
slot.y = nextY;
slotContainerArr[2].addChild(slot);
slotArr2.splice(toDel, 1);//remove from array
}
}
}
If I understood the code correctly, with quick check:
Sprites can have only one parent. If you check the Sprite object, it actually has a parent property. So slotArr1 and slotArr2 have identical Sprites and that fact doesn't change id you slice them. Then when you are assigning them to different containers, they get moved from one container to the other. You can reuse textures sure, but one Sprite can only have on parent.

How can I detect a specific 3d model collision three.js

I am trying to make clickable 3d objects with Leap Motion. I have two 3D models, IronMan helmet and a Hammer of Thor. If one of those two object is selected, then will change color. For the Iron Man will be green and for the Hammer will be white. But when I am selecting the Hammer, it changes to green instead of white. I use a cube as a pointer to select the object. Can you help?
This is the code to insert 3d models:
var colladaMeshlist = [];
model = new THREE.Object3D()
var object;
var skin;
var objectScale = 1.5;
rotX=0, rotY=0, rotZ=0;
var loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true;
loader.load( 'models/IronMan.dae', function (collada) {
object = collada.scene;
object.scale.x = object.scale.y = object.scale.z = objectScale;
object.position.x= 20;
object.position.y= -40;
object.position.z= 0;
object.rotation.x= rotX;
object.rotation.y= rotY;
object.rotation.z= rotZ;
object.name="IronMan";
colladaMeshlist.push(object);
model.add(object);
});
scene.add(model);
model2 = new THREE.Object3D()
var object2;
var skin2;
var objectScale2 = 1;
posX=0, posY=-40, posZ=0;
rotX=0, rotY=0, rotZ=0;
var loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true;
loader.load( 'models/Hammer.dae', function (collada) {
object2 = collada.scene;
object2.scale.x = object2.scale.y = object2.scale.z = objectScale2;
object2.position.x= -20;
object2.position.y= -20;
object2.position.z= posZ;
object2.rotation.x= rotX;
object2.rotation.y= rotY;
object2.rotation.z= rotZ;
object2.name="Hammer";
colladaMeshlist.push(object2);
model2.add(object2);
});
scene.add(model2);
This is the code for selecting the objects:
var originPoint = cube.position.clone();
for(var vertexIndex = 0; vertexIndex < cube.geometry.vertices.length; vertexIndex++)
{
var localVertex = cube.geometry.vertices[vertexIndex].clone();
var globalVertex = localVertex.applyMatrix4( cube.matrix );
var directionVector = globalVertex.sub( cube.position );
var ray = new THREE.Raycaster( originPoint, directionVector.clone().normalize() );
var collisionResults = ray.intersectObjects(colladaMeshlist, true);
if(collisionResults.length > 0 && collisionResults[0].distance < directionVector.length())
{
collisionResults[0].object.material.color.setHex(0x4CAF50);
}
else if (collisionResults.length > 0 && collisionResults[1].distance < directionVector.length())
{
collisionResults[1].object.material.color.setHex(0xffffff);
}
}

Unexpected behaviour in famo.us javascript

The code below creates up the elements for a grid, and arranges it using the transformOut method. This part works fine, but I then want the grid to collapse in to the centre on mousedown, and spring back out again on mouseup. However, all subsequent calls to either the transformIn or transformOut function result in the items going in and out. A working example is here:
http://codepen.io/timsig/pen/JdXYwE
Code as follows, thanks for any help.
define('main', function (require, exports, module) {
var Engine = require('famous/core/Engine');
var View = require('famous/core/View');
var Surface = require('famous/core/Surface');
var Modifier = require('famous/core/Modifier');
var StateModifier = require('famous/modifiers/StateModifier');
var EventHandler = require('famous/core/EventHandler');
var PhysicsEngine = require('famous/physics/PhysicsEngine');
var Transitionable = require('famous/transitions/Transitionable');
var SpringTransition= require('famous/transitions/SpringTransition');
var Particle = require('famous/physics/bodies/Particle');
var Drag = require('famous/physics/forces/Drag');
var RepulsionForce = require('famous/physics/forces/Repulsion');
var Wall = require('famous/physics/constraints/Wall');
var Random = require('famous/math/Random');
var Transform = require('famous/core/Transform');
Transitionable.registerMethod('spring', SpringTransition);
var context = Engine.createContext();
var cols = 5;
var rows = 5;
var gridSize = Math.min(window.innerWidth, window.innerHeight) / 1.5;
var itemSize = gridSize / (cols + 1);
var gridItems = [];
var transformOutArray = [itemSize / 2 - gridSize / 2,
(itemSize / 2 - gridSize / 2) / 2,
0,
(gridSize / 2 - itemSize / 2) / 2,
gridSize / 2 - itemSize / 2];
var transformInArray = Array.prototype.slice.call(transformOutArray);
transformInArray.reverse();
var cameraView = new View();
var camera = new Modifier({
origin: [0.5, 0.5],
align: [0.5, 0.5]
});
context.add(camera).add(cameraView);
function createGridItems(){
for (var r = 0; r < rows; r += 1){
for (var c = 0; c < cols; c += 1){
var gridItem = new Surface({
size: [itemSize, itemSize],
properties:{
backgroundColor: '#aa62bb'
},
content: r + "," + c
});
gridItem.mod = new StateModifier({
origin: [0.5, 0.5],
align: [0.5, 0.5],
transform: Transform.identity
});
gridItem.idx = gridItems.length;
gridItem.transformOutrs = transformOutArray[r];
gridItem.transformOutcs = transformOutArray[c];
gridItem.transformInrs = transformInArray[r];
gridItem.transformIncs = transformInArray[c];
gridItems.push(gridItem);
cameraView.add(gridItem.mod).add(gridItem);
}
}
}
function transformOut(){
console.log('transform out')
for (var i = 0; i < gridItems.length; i+=1){
var index = i;
var gridItem = gridItems[index];
var tran = Transform.translate(gridItem.transformOutrs, gridItem.transformOutcs);
gridItem.mod.setTransform(tran, {
method: 'spring',
dampingRatio: 0.5,
period: 600
});
}
}
function transformIn(){
console.log('transform in');
for (var j = 0; j < gridItems.length; j+=1){
var index = j;
var gridItem = gridItems[index];
var tran = Transform.translate(gridItem.transformInrs, gridItem.transformIncs);
gridItem.mod.setTransform(tran, {
method: 'spring',
dampingRatio: 0.5,
period: 600
});
}
}
createGridItems();
console.log (transformOutArray);
console.log (transformInArray);
transformOut();
Engine.on('mousedown', transformIn);
Engine.on('mouseup', transformOut);
});
Setting the Transform back to the identity will return items back to their default on transform. Currently they are transitioning back to original once the new transform is set, then apply the new transform. You are only reversing their order with the new transforms.
function transformIn(){
console.log('transform in');
for (var j = 0; j < gridItems.length; j+=1){
var index = j;
var gridItem = gridItems[index];
gridItem.mod.setTransform(Transform.identity, {
method: 'spring',
dampingRatio: 0.5,
period: 600
});
}
}
Example snippet:
define('main', function (require, exports, module) {
var Engine = require('famous/core/Engine');
var View = require('famous/core/View');
var Surface = require('famous/core/Surface');
var Modifier = require('famous/core/Modifier');
var StateModifier = require('famous/modifiers/StateModifier');
var EventHandler = require('famous/core/EventHandler');
var PhysicsEngine = require('famous/physics/PhysicsEngine');
var Transitionable = require('famous/transitions/Transitionable');
var SpringTransition= require('famous/transitions/SpringTransition');
var Particle = require('famous/physics/bodies/Particle');
var Drag = require('famous/physics/forces/Drag');
var RepulsionForce = require('famous/physics/forces/Repulsion');
var Wall = require('famous/physics/constraints/Wall');
var Random = require('famous/math/Random');
var Transform = require('famous/core/Transform');
Transitionable.registerMethod('spring', SpringTransition);
var context = Engine.createContext();
var cols = 5;
var rows = 5;
var gridSize = Math.min(window.innerWidth, window.innerHeight) / 1.5;
var itemSize = gridSize / (cols + 1);
var gridItems = [];
var transformOutArray = [itemSize / 2 - gridSize / 2,
(itemSize / 2 - gridSize / 2) / 2,
0,
(gridSize / 2 - itemSize / 2) / 2,
gridSize / 2 - itemSize / 2];
var transformInArray = Array.prototype.slice.call(transformOutArray);
transformInArray.reverse();
var cameraView = new View();
var camera = new Modifier({
origin: [0.5, 0.5],
align: [0.5, 0.5]
});
context.add(camera).add(cameraView);
function createGridItems(){
for (var r = 0; r < rows; r += 1){
for (var c = 0; c < cols; c += 1){
var gridItem = new Surface({
size: [itemSize, itemSize],
properties:{
backgroundColor: '#aa62bb'
},
content: r + "," + c
});
gridItem.mod = new StateModifier({
origin: [0.5, 0.5],
align: [0.5, 0.5],
transform: Transform.identity
});
gridItem.idx = gridItems.length;
gridItem.transformOutrs = transformOutArray[r];
gridItem.transformOutcs = transformOutArray[c];
gridItem.transformInrs = transformInArray[r];
gridItem.transformIncs = transformInArray[c];
gridItems.push(gridItem);
cameraView.add(gridItem.mod).add(gridItem);
}
}
}
function transformOut(){
console.log('transform out');
for (var i = 0; i < gridItems.length; i+=1){
var index = i;
var gridItem = gridItems[index];
var tran = Transform.translate(gridItem.transformOutrs, gridItem.transformOutcs);
gridItem.mod.setTransform(tran, {
method: 'spring',
dampingRatio: 0.5,
period: 600
});
}
}
function transformIn(){
console.log('transform in');
for (var j = 0; j < gridItems.length; j+=1){
var index = j;
var gridItem = gridItems[index];
gridItem.mod.setTransform(Transform.identity, {
method: 'spring',
dampingRatio: 0.5,
period: 600
});
}
}
createGridItems();
console.log (transformOutArray);
console.log (transformInArray);
transformOut();
Engine.on('mousedown', transformIn);
Engine.on('mouseup', transformOut);
});
require(['main']);
<script src="http://requirejs.org/docs/release/2.1.16/minified/require.js"></script>
<script src="http://code.famo.us/lib/requestAnimationFrame.js"></script>
<script src="http://code.famo.us/lib/classList.js"></script>
<script src="http://code.famo.us/lib/functionPrototypeBind.js"></script>
<link rel="stylesheet" type="text/css" href="http://code.famo.us/famous/0.3.5/famous.css" />
<script src="http://code.famo.us/famous/0.3.5/famous.min.js"></script>
NOTE: setTransform is now deprecated in Famo.us
Deprecated: Prefer transformFrom with static Transform, or use a TransitionableTransform.

Faulty Logic in this image color equalization algorithm

Somewhere in my code, I seem to be doing something wrong and I cannot tell which part is going awry. I've printed to console the values I'm getting from the various arrays and it seems to match up. Then when I run the equalization function (a la Wikipedia-Histogram Equalization) my output image is close to total black. I was trying to interpret this guy's php into javascript just to test some stuff out and figured I did a decent job. But I'm not an expert.
The pertinent parts:
function imageLoaded(ev) {
element = document.getElementById("canvas1");
c = element.getContext("2d");
im = ev.target; // the image
// read the width and height of the canvas
width = element.width;
height = element.height;
// stamp the image on the left of the canvas:
c.drawImage(im, 0, 0);
// get all canvas pixel data
imageData = c.getImageData(0, 0, width, height);
w2 = width / 2;
var reds = new Array();
var greens = new Array();
var blues = new Array();
var freqR = new Array();
var freqG = new Array();
var freqB = new Array();
if (imageData){
buildHistograms(reds, greens,blues);
buildFrequencies(reds, greens, blues, freqR, freqG, freqB);
}
var alpha = 255/(w2*height);
// run through the image
for (y = 0; y < height; y++) {
inpos = y * width * 4; // *4 for 4 ints per pixel
outpos = inpos + w2 * 4;
for (x = 0; x < w2; x++) {
//reads pixel data(of img c)to each channel of rgb
r = imageData.data[inpos++];
g = imageData.data[inpos++];
b = imageData.data[inpos++];
a = imageData.data[inpos++];
//using histogram eqalization formula:
adjR = freqR[r]*alpha;
adjG = freqG[g]*alpha;
adjB = freqB[b]*alpha;
//assigns pixel data of output image
imageData.data[outpos++] = adjR;
imageData.data[outpos++] = adjG;
imageData.data[outpos++] = adjB;
imageData.data[outpos++] = a;
}
}
// put pixel data on canvas
c.putImageData(imageData, 0,0);
}
im = new Image();
im.onload = imageLoaded;
im.src = "Lenna.png";
function buildHistograms(reds,greens,blues){
//run through image building histogram
for (y=0; y < height; y++){
inpos = y * width *4;
for (x=0; x < w2; x++){
rd = imageData.data[inpos++];
g = imageData.data[inpos++];
b = imageData.data[inpos++];
a = imageData.data[inpos++];
// Add counts to our histogram arrays for each color.
reds.push(rd);
greens.push(g);
blues.push(b);
}
}
// Sort them by keys into order
reds.sort(function(a,b){return a-b});
greens.sort(function(a,b){return a-b});
blues.sort(function(a,b){return a-b});
}
function buildFrequencies(reds, greens, blues, freqR, freqG, freqB){
// Build frequency charts for all colors: takes REDS GREENS BLUES from buildHistograms and places them on top of each other accordingly
for(i=0; i<=255; i++){
sumR=0;
sumG=0;
sumB=0;
for(j=0; j<= i; j++){
if (reds[j]){sumR+=reds[j];}
if (greens[j]){sumG+=greens[j];}
if (blues[j]){sumB+=blues[j];}
}
freqR[i] = sumR;
freqG[i] = sumG;
freqB[i] = sumB;
}
}
Any help is appreciated, Thanks.
Looks like my build frequencies section was all wrong. I modified it in this way:
var len = reds.length;
for (j=0; j < len; j++) {
var rCurrVal = reds[j];
var gCurrVal = greens[j];
var bCurrVal = blues[j];
if (freqR.hasOwnProperty(rCurrVal)) {
freqR[rCurrVal] += 1;
} else {
freqR[rCurrVal] = 1;
}
if (freqG.hasOwnProperty(gCurrVal)) {
freqG[gCurrVal] += 1;
} else {
freqG[gCurrVal] = 1;
}
if (freqB.hasOwnProperty(bCurrVal)) {
freqB[bCurrVal] += 1;
} else {
freqB[bCurrVal] = 1;
}
}
for (i=0; i<255; i++){
if ($.inArray(i,reds)===-1){freqR[i]=0;}
if ($.inArray(i,greens)=== -1){freqG[i]=0;}
if ($.inArray(i,blues)=== -1){freqB[i]=0;}
if (i>0){
freqR[i]+=freqR[i-1];
freqG[i]+=freqG[i-1];
freqB[i]+=freqB[i-1];
}
}

Categories

Resources