javascriptcanvascomputer-visiontemplate-matching

JS: Locate image/canvas inside of another canvas, and then rectangle


How can I do something like this? Image one: enter image description here

Image two: enter image description here

And how can I do like this:

const image1 = document.querySelector("#imgone");
const image2 = document.querySelector("#imgtwo");

let ctx1 = image1.getContext("2d");
let ctx2 = image2.getContext("2d");

function locate(context1, context2) {
    #?????? 
    return "..."
}

function rectangle(context, corner1,corner2,corner3,corner4) {
    #??????
    return "..."
}



[corner1,corner2,corner3,corner4] = locate(ctx,ctx2);
rectangle(ctx2, corner1,corner2,corner3,corner4);



Basically a computer-vision task. Is it possible? How can you do it?


Solution

  • it is me sld on a different account. I have figured it out, and would like to show you.

    My solution is very inneficient, but I have this code.

    function canvas(w = 300, h = 150) {
      let r = document.createElement("canvas")
      r.height = h
      r.width = w
      return r
    }
    
    function points(startx, starty, w, h) {
      return [
        [startx, starty],
        [startx + w, starty],
        [startx + w, starty + h],
        [startx, starty + h]
      ]
    }
    
    
    function getPixelColor(canvas, x, y) {
      return Array.from(canvas.getContext("2d").getImageData(x, y, 1, 1).data)
    }
    
    function gpc(canvas, x, y, sx, sy) {
      return Array.from(canvas.getContext("2d").getImageData(x, y, sx, sy).data)
    }
    
    function gap(canvas) {
      return gpc(canvas, 0, 0, canvas.width, canvas.height)
    }
    
    function gx(index, w = 300, h = 150, nx = 5, ny = 5) {
      let fpd = []
      for (let i = 0; i < w; i += nx) {
        for (let ii = 0; ii < h; ii += ny) {
          fpd.push([i, ii])
        }
      }
    
      return fpd[index]
    }
    
    // function genPixels(canvas,nx=5,ny=5) {
    //    let ctx = canvas.getContext("2d")
    //    let fpd = []
    //    for (let i = 0; i < canvas.width; i+=nx) {
    //     for (let ii = 0; ii < canvas.height; ii+=ny) {
    //         fpd.push(Array.from(ctx.getImageData(i,ii,nx,ny).data))
    //     }
    //    }
    //    return fpd
    // }
    
    function chunk(n, c) {
      return n.reduce((n, r, t) => {
        const o = Math.floor(t / c);
        return n[o] = [].concat(n[o] || [], r), n
      }, [])
    }
    
    
    function findImg(parent, canvas, ih, iw) {
      if (parent.tagName !== "canvas") {
        console.log("parent argument must be canvas. use canvas.content.drawImage on a new canvas to convert img to canvas.")
      }
      if (canvas.tagName === "img") {
        console.log("canvas argument must be type canvas. use canvas.context.drawImage on a new canvas to convert img to canvas.")
      }
      let allPixels = gap(parent)
      let cp = gap(canvas)
      let chunks = chunk(allPixels, ih * iw * 4)
      for (let i = 0; i < chunks.length; i += 1) {
        if (String(chunks[i]) === String(cp)) {
          let start = gx(i, parent.width, parent.height, iw, ih)
          return points(start[0], start[1], iw, ih)
        }
      }
      return false
    }
    
    let pointsc = findImg(canvas(), canvas(5, 5), 5, 5);
    let dim = pointsc[2].reverse()
    this.strokeStyle = "black"
    let yours = document.querySelector("#yours")
    yours.getContext("2d").strokeRect(0, 0, dim[0], dim[1])
    <canvas id="yours"></canvas>

    Minified:

    function canvas(t=300,n=150){let e=document.createElement("canvas");return e.height=n,e.width=t,e}function points(t,n,e,a){return[[t,n],[t+e,n],[t+e,n+a],[t,n+a]]}function getPixelColor(t,n,e){return Array.from(t.getContext("2d").getImageData(n,e,1,1).data)}function gpc(t,n,e,a,r){return Array.from(t.getContext("2d").getImageData(n,e,a,r).data)}function gap(t){return gpc(t,0,0,t.width,t.height)}function gx(t,n=300,e=150,a=5,r=5){let o=[];for(let t=0;t<n;t+=a)for(let n=0;n<e;n+=r)o.push([t,n]);return o[t]}function chunk(t,n){return t.reduce((t,e,a)=>{const r=Math.floor(a/n);return t[r]=[].concat(t[r]||[],e),t},[])}function findImg(t,n,e,a){"CANVAS"!==t.tagName&&console.log("parent argument must be canvas. use canvas.content.drawImage on a new canvas to convert img to canvas."),"IMG"===n.tagName&&console.log("canvas argument must be type canvas. use canvas.context.drawImage on a new canvas to convert img to canvas.");let r=gap(t),o=gap(n),c=chunk(r,e*a*4);for(let n=0;n<c.length;n+=1)if(String(c[n])===String(o)){let r=gx(n,t.width,t.height,a,e);return points(r[0],r[1],a,e)}return!1}
    

    I will be doing an example with just two white images.

    let pointsc = findImg(canvas(), canvas(5,5), 5, 5);
    let dim = pointsc[2].reverse()
    this.strokeStyle="black"
    document.querySelector("#yours").getContext("2d").strokeRect(0,0,dim[0],dim[1])
    

    This is extremely inefficient, and I am up for suggestions, for example how to not use as many loops.