<html> <body> <canvas id="canvas" width="600" height="450" style="float:left"></canvas> <canvas id="out" width="600" height="450" style="float:left"></canvas> <script> let img = new Image(); img.src = 'lines1.png'; let canvas = document.getElementById('canvas'); let ctx = canvas.getContext('2d'); let out = document.getElementById('out'); let ctxOut = out.getContext('2d'); img.onload = function() { ctx.drawImage(img, 0, 0); img.style.display = 'none'; let start = new Date(); drawRanges(); let end = new Date(); console.log('time', end.getTime() - start.getTime()); }; function rangeLen(range) { return Math.sqrt( (range.x2 - range.x1) * (range.x2 - range.x1) + (range.y2 - range.y1) * (range.y2 - range.y1) ); }; let unique = (array) => { return Array.from(new Set(array)); }; let merge = (arrays) => { return [].concat.apply([], arrays); }; let rangeOverlap = (min1, max1, min2, max2) => { if (min1 > max1 || min2 > max2) { throw new Error("Invalid range"); } if (max2 <= min1 || min2 >= max1) { return 0; } if (min1 <= min2 && max1 >= max2) { return max2 - min2; } if (min1 >= min2 && max1 <= max2) { return max1 - min1; } if (min1 >= min2 && max1 >= max2 && max2 >= min1) { return max2 - min1; } if (min1 <= min2 && max1 >= min2 && max2 >= max1) { return max1 - min2; } return 0; }; let rangeCollidesWithRanges = (range, ranges) => { let results = []; for (var i = 0; i < ranges.length; i++) { let overlap = rangeOverlap(range.x1, range.x2, ranges[i].x1, ranges[i].x2); if (overlap > 0) { results.push(ranges[i]); } } return results; }; function getRanges(data, width, height) { let inRange = false; let ranges = []; let range = null; let prevRowRanges = []; let rowRanges = []; let bodies = []; let cnt = 0; let startRange = (x, y) => { return { x1: x, y1: y, x2: 0, y2: 0 }; }; let endRange = (range, x, y) => { range.x2 = x; range.y2 = y; ranges.push(range); rowRanges.push(range); let cols = rangeCollidesWithRanges(range, prevRowRanges); if (cols.length == 0) { range.bodies = [cnt]; bodies.push(cnt); cnt += 1; } else { range.bodies = unique(merge(cols.map((col) => col.bodies))); } return null; }; let doPixel = (x, y, r, g, b, a) => { // pixel filter here inRange = r < 200; if (inRange) { if (!range) { range = startRange(x, y); } } else { if (range) { range = endRange(range, x, y); } } if (y + 1 == height) { if (range) { range = endRange(range, x, y); } } }; for (let y = 0; y < height; y += 1) { prevRowRanges = rowRanges; rowRanges = []; for (let x = 0; x < width; x += 1) { let p = (y * width * 4) + (x * 4); doPixel(x, y, data[p], data[p + 1], data[p + 2], data[p + 3]); } } return { ranges: ranges, bodies: bodies }; } function drawRange(ctx, range) { ctx.beginPath(); ctx.moveTo(range.x1, range.y1); ctx.lineTo(range.x2, range.y2); ctx.stroke(); } function circle(ctx, x,y,r) { ctxOut.beginPath(); ctxOut.strokeStyle = 'black'; ctx.arc(x, y, r, 0, 2 * Math.PI); ctxOut.stroke(); } function drawRanges() { let width = canvas.width; let height = canvas.height; let data = ctx.getImageData(0, 0, width, height); let rangesAndBodies = getRanges(data.data, data.width, data.height); let ranges = rangesAndBodies.ranges; let bodies = rangesAndBodies.bodies; let colors = ['red', 'yellow', 'green', 'magenta', 'teal', 'purple', 'blue', 'navy', 'orange']; //console.log('ranges', rangesAndBodies); ctxOut.lineWidth = 1; for (var i = 0; i < bodies.length; i++) { var b = bodies[i]; let bodyRanges = ranges.filter((range) => { return range.bodies.indexOf(b) >= 0; }); ctxOut.strokeStyle = colors[i % colors.length]; bodyRanges.forEach(function(range, i) { drawRange(ctxOut, range); }); let minXy = bodyRanges.reduce(function(r1, r2) { return (r1.x1 < r2.x1 ? r1 : r2); }); let minYx = bodyRanges.reduce(function(r1, r2) { return (r1.y1 < r2.y1 ? r1 : r2); }); let maxXy = bodyRanges.reduce(function(r1, r2) { return (r1.x2 > r2.x2 ? r1 : r2); }); let maxYx = bodyRanges.reduce(function(r1, r2) { return (r1.y2 > r2.y2 ? r1 : r2); }); circle(ctxOut, minXy.x1,minXy.y1, 3); circle(ctxOut, minYx.x1,minYx.y1, 3); circle(ctxOut, maxXy.x2,maxXy.y2, 3); circle(ctxOut, maxYx.x2,maxYx.y2, 3); //console.log('rect', minX,minY,maxX-minX,maxY-minY); ctxOut.beginPath(); ctxOut.strokeStyle = colors[(i + 2) % colors.length]; ctxOut.rect(minXy.x1, minYx.y1, maxXy.x2 - minXy.x1, maxYx.y2 - minYx.y1); ctxOut.stroke(); } } </script> </body> </html>
75000cookie-checkBasic Image recognition (Javascript)