2017-05-04 10 views
0

イメージを別のイメージから抽出するために、マトリックスでピクセル操作を実践したい。イメージ変換マトリックス

これは私がCSSの変換行列でやっていることです: https://www.noelshack.com/2017-18-1493893008-capture-2.png

左画像「L」で、私は画像の周囲4点の場所を持っていると右画像「R」で、私はのコンテンツを見つけます変換。私はプロパティを使用しているために

は、CSSの変換が、私は、手動で操作をしたいです。

CSSのバージョン:

matrix3d(1.5456325781948308,1.6561987730956724,0,0.0012239101773909712,-0.4663849104791486,2.218793881308064,0,0.0009095626603861196,0,0,1,0,12.247969030166722,-17.754955132517754,0,0.9951722722714726) 

マトリックス 'M':

[[1.5456325781948308, 1.6561987730956724, 0, 0.0012239101773909712], 
[-0.4663849104791486, 2.218793881308064, 0, 0.0009095626603861196], 
[0, 0, 1, 0], 
[12.247969030166722, -17.754955132517754, 0, 0.9951722722714726]] 

私は彼らのピクセルが L.

画像内の位置に関連しているか画像Rの各ピクセルについて知りたいです

たとえば、Rの(0,0)はRの(52,203)です。 そのために、この計算を行います。

M * P = P' 

Pは P」がL画像

Pマトリックスの画素位置がそのように定義されているR画像の画素位置である:

[[x], 
[y], 
[0], 
[1]] 

だから0,0位置について私はこれを行う:

[[1.5456325781948308, 1.6561987730956724, 0, 0.0012239101773909712], 
[-0.4663849104791486, 2.218793881308064, 0, 0.0009095626603861196], 
[0, 0, 1, 0], 
[12.247969030166722, -17.754955132517754, 0, 0.9951722722714726]] 

X 

[[0], 
[0], 
[0], 
[1]] 

= 

[[0.0012239101773909712], 
[0.0009095626603861196], 
[0], 
[0.9951722722714726]] 

これは結果ですが、2番目のコンポーネント: (0.0012239101773909712,0.0009095626603861196) が予想よりも小さすぎます。問題を見つけるのを助けてくれますか?

scincerly、 MatrixCuriosity。

+0

この行列は、直接変換L-> Rまたは後の1つのR-> Lの行列ですか? 2D変換で行列が3x3ではなく4x4になるのはなぜですか?シフトコンポーネント(12/-17?)が小さすぎます。 – MBo

+0

相互参照:4点とその画像が与えられた行列を見つける手順については、https://math.stackexchange.com/a/339033/35416を参照してください。答えとコメントには、JavaScript/CSSデモが動作しています。 – MvG

答えて

0

これらは同次座標です。入力としていくつかの[x1、y1、z1、1]が与えられていますが、実際の位置は[x2/w2、y2/w2、z2/w2]です。最後の座標で割ります。

しかし、これは期待した結果には至りません。また、行列をその付属語(または等価的に逆行列)で置き換えることも、転置することもできません。これらの両方とも間違っているのは簡単なので、あなたが実際に持っているべきバージョンとそうでなければならないバージョンをあまり考えずに、4つの選択肢すべてを試してみてください(副詞の有無にかかわらず) 。

あなたのものではありません。だから、私の次の最善の策は、CSSプロパティtransform-originは、それが50% 50% 0の初期値だである一方、あなたが期待する座標は、画像の一部の隅から測定されていることになりますので、座標系の原点は、オブジェクトの中心に実際にあります。実際には、このためにHTMLとCSSを共有

私はこの仮定を検証するために許可されている場合があります。これがあなたに当てはまるかどうかを確認する必要があります。私は最後にa projective image transformation demoからanswer a question about finding the transformを作成したときに、そのような問題を避けるために意図的にtransform-origin: 0 0;(およびこれのさまざまなベンダープレフィックス版)を設定したことを覚えています。

0

ありがとうございました。

ただ一つのことhttps://math.stackexchange.com/a/339033] [私はあなたのリンクをたどると、私は私が欲しいものを見つける、私はピクセル関連L < -R

を見つけるために、C行列を反転させる必要があり、私はのアイデアを与えるために私のコードを共有しますあなたはあなたが機能computeMat(で私の実装を見つけることができます しなければならない)

<style> 
body { 
    touch-action: none; 
    overflow-y: hidden; 
} 
#canvas_toeic 
{ 
    position:absolute; 
    top:0; 
    left:0; 
} 
</style> 

<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/mathjs/3.12.2/math.min.js"></script> 

</head> 



<body> 
    <canvas id="canvas_toeic" width="600" height="400"> 
    </canvas> 

<script type="text/javascript"> 

    var image = new Image(); 
    image.src = 'image.jpg'; 
    image.onload = function() { 

     var c = document.getElementById("canvas_toeic"); 
     var ratio = image.width/image.height; 
     var canvasWidth = document.body.clientWidth; 
     var canvasHeight = canvasWidth/ratio; 


     if(document.body.clientHeight < canvasHeight) 
     { 
      canvasHeight = document.body.clientHeight; 
      canvasWidth = canvasHeight * ratio; 
     } 

     var canvasLargeur = canvasWidth; 
     var canvasLongueur = canvasHeight; 

     if(canvasLargeur < canvasHeight) { 
      canvasLargeur = canvasHeight; 
      canvasLongueur = canvasWidth; 
     } 

     var canvasPixelRatio = canvasLargeur/image.width; 

     c.setAttribute("width", canvasWidth); 
     c.setAttribute("height", canvasHeight); 

     var ctx = c.getContext("2d"); 
     var idPoint = -1; 

     var points = []; 
     for(var i = 0; i < 4; i++) 
      points[i] = {x:0, y:0}; 

     var marginImage = Math.round(40 * canvasPixelRatio); 

     points[0].x = marginImage; 
     points[0].y = marginImage; 
     points[1].x = marginImage; 
     points[1].y = canvasHeight - marginImage; 
     points[2].x = canvasWidth - marginImage; 
     points[2].y = canvasHeight - marginImage; 
     points[3].x = canvasWidth - marginImage; 
     points[3].y = marginImage; 

     function draw(points) { 
      console.log("draw"); 

      // Fond 
      ctx.fillStyle = "#222"; 
      ctx.fillRect(0, 0, canvasWidth, canvasHeight); 

      ctx.drawImage(image, marginImage, marginImage, canvasWidth - marginImage * 2, canvasHeight - marginImage * 2); // this fait référence à l'objet courant (=image) 

      if(idPoint == -1) 
       ctx.lineWidth = 3 * canvasPixelRatio; 
      else 
       ctx.lineWidth = 5 * canvasPixelRatio; 

      ctx.beginPath();  // Début du chemin 
      ctx.lineJoin = "round"; 
      ctx.lineCap = "round"; 
      ctx.strokeStyle = "rgba(64, 128, 255, 0.5)"; 
      ctx.moveTo(points[0].x, points[0].y); // Le tracé part du point 50,50 
      for(var i = 0; i < 4; i++) 
       ctx.lineTo(points[i].x, points[i].y); // Un segment est ajouté vers 200,200 
      ctx.closePath();  // Fermeture du chemin (facultative) 
      ctx.stroke(); 


      for(var i = 0; i < 4; i++) 
      { 
       var radius = 30 * canvasPixelRatio; 

       if(idPoint == i) 
        radius = 60 * canvasPixelRatio; 

       ctx.beginPath(); 
       ctx.arc(points[i].x, points[i].y, radius, 0, Math.PI*2, true); 
       ctx.strokeStyle = "#FF8800"; 
       ctx.fillStyle = "rgba(255, 128, 0, 0.5)"; 
       ctx.fill(); 
       ctx.stroke(); 
      } 

      if(idPoint != -1) 
      { 
       var zoomWidth = canvasWidth/3; 
       var zoomHeight = canvasHeight/3; 
       var zoomMargin = 5; 
       var zoomAroundWidth = 50; 
       var zoomAroundHeight = zoomAroundWidth/ratio; 

       var positionMouse = points[idPoint]; 
       var imagePositionX = (positionMouse.x - marginImage)/(canvasWidth - marginImage * 2) * image.width; 
       var imagePositionY = (positionMouse.y - marginImage)/(canvasHeight - marginImage * 2) * image.height; 

       var zoomX = 0; 
       var zoomY = 0; 

       if(imagePositionX < image.width/2) 
        zoomX = canvasWidth - zoomWidth; 
       if(imagePositionY < image.height/2) 
        zoomY = canvasHeight - zoomHeight; 

       ctx.fillStyle = "#F08"; 
       ctx.fillRect(zoomX, zoomY, zoomWidth, zoomHeight); 
       ctx.drawImage(image, imagePositionX - zoomAroundWidth, imagePositionY - zoomAroundHeight, zoomAroundWidth * 2, zoomAroundHeight * 2, zoomX + zoomMargin, zoomY + zoomMargin, zoomWidth - zoomMargin * 2, zoomHeight - zoomMargin * 2); 

       ctx.lineWidth = 3 * canvasPixelRatio; 

       ctx.beginPath();  
       ctx.lineJoin = "round"; 
       ctx.lineCap = "round"; 
       ctx.strokeStyle = "rgba(255, 0, 0, 0.5)"; 
       ctx.moveTo(zoomX, zoomY + zoomHeight/2);  
       ctx.lineTo(zoomX + zoomWidth, zoomY + zoomHeight/2); 
       ctx.moveTo(zoomX + zoomWidth/2, zoomY);  
       ctx.lineTo(zoomX + zoomWidth/2, zoomY + zoomHeight); 
       ctx.closePath(); 
       ctx.stroke(); 
      } 
     } 

     function nearPoint(points, x, y) 
     { 
      var radiusDetection = 60 * canvasPixelRatio; 
      var distances = []; 

      for(i = 0; i < 4; i++) { 
       var mx = x - points[i].x; 
       var my = y - points[i].y; 
       distances[i] = Math.sqrt(mx * mx + my * my); 
      } 

      minI = 0; 
      minD = distances[0]; 

      for(i = 1; i < 4; i++) 
      { 
       if(minD > distances[i]) 
       { 
        minD = distances[i]; 
        minI = i; 
       } 
      } 

      if(minD <= radiusDetection) 
       return minI; 

      return -1; 
     } 

     function getTouchPosition(e) 
     { 
      var target = null; 
      var mouse = null; 

      if(e.changedTouches != undefined) 
      { 
       var touches = e.changedTouches; 
       mouse = touches[0]; 
       target = touches[0].target; 
      } 
      else if(e.originalTarget != undefined) 
      { 
       mouse = e; 
       target = e.originalTarget; 
      } 

      var coordX = 0; 
      var coordY = 0; 

      if(mouse.layerX != undefined) 
      { 
       coordX = mouse.layerX; 
       coordY = mouse.layerY; 
      } 
      else 
      { 
       coordX = mouse.pageX; 
       coordY = mouse.pageY; 
      } 

      var x = coordX - target.offsetLeft; 
      var y = coordY - target.offsetTop; 

      if(x < 0) x = 0; 
      if(y < 0) y = 0; 
      if(x >= canvasWidth) x = canvasWidth - 1; 
      if(y >= canvasHeight) y = canvasHeight - 1; 

      return {'x':x, 'y':y}; 
     } 

     function mouseDown(e) 
     { 
      var position = getTouchPosition(e); 

      idPoint = nearPoint(points, position.x, position.y); 

      if(idPoint == -1) 
      { 
       if(position.x < marginImage * 3 && position.y < marginImage * 3) 
       { 
        computeMat(); 
       } 
      } 
     } 

     function mouseUp(e) 
     { 
      if(idPoint != -1) 
      { 
       idPoint = -1; 
       draw(points); 
      } 
     } 

     function mouseMove(e) 
     { 
      if(idPoint != -1) 
      { 
       var position = getTouchPosition(e); 
       points[idPoint].x = position.x; 
       points[idPoint].y = position.y; 
       draw(points); 
      } 
     } 

     function cancelDefault(e) 
     { 
      e.preventDefault(); 
     } 

     function matStep12(pts) 
     { 
      var matP = [ 
       [pts[0].x, pts[1].x, pts[2].x], 
       [pts[0].y, pts[1].y, pts[2].y], 
       [1, 1, 1] 
       ]; 

      var vecP = [[pts[3].x], [pts[3].y], [1]]; 

      var matPi = math.inv(matP); 
      var vecPi = math.multiply(matPi, vecP); 

      var result = [ 
        [pts[0].x * vecPi[0][0], pts[1].x * vecPi[1][0], pts[2].x * vecPi[2][0]], 
        [pts[0].y * vecPi[0][0], pts[1].y * vecPi[1][0], pts[2].y * vecPi[2][0]], 
        [vecPi[0][0], vecPi[1][0], vecPi[2][0]] 
       ]; 

      return result; 
     } 

     function distance(a, b) 
     { 
      var mx = b.x - a.x; 
      var my = b.y - a.y; 

      return Math.sqrt(mx * mx + my * my); 
     } 

     function computeMat() 
     { 
      var pts = getPointRelativePosition(); 

      var widthT = distance(pts[0], pts[3]); 
      var widthB = distance(pts[1], pts[2]); 
      var heightL = distance(pts[0], pts[1]); 
      var heightR = distance(pts[2], pts[3]); 

      var maxWidth = (widthT > widthB) ? widthT : widthB; 
      var maxHeight = (heightL > heightR) ? heightL : heightR; 
      var imgWidth = Math.round(maxWidth); 
      var imgHeight = Math.round(maxHeight); 


      var matA = matStep12(pts); 
      var matB = matStep12([{x:0,y:0}, {x:0,y:maxHeight}, {x:maxWidth,y:maxHeight}, {x:maxWidth,y:0}]); 
      var matC = math.multiply(matB, math.inv(matA)); 
      var matCi = math.inv(matC); 

      console.log('width:' + imgWidth + ', height:' + imgHeight); 
      printMat(matC); 


      // construct image with transformation matrice 

      imageData = ctx.createImageData(imgWidth, imgHeight); 

      var tempCanvas = document.createElement('canvas'); 
      var tempCtx = tempCanvas.getContext('2d'); 
      tempCanvas.width = image.width; 
      tempCanvas.height = image.height; 
      tempCtx.drawImage(image, 0, 0, image.width, image.height); 
      var imageDataSrc = tempCtx.getImageData(0, 0, image.width, image.height); 

      var mz = [matCi[0][2], matCi[1][2], matCi[2][2]]; 

      for(var y = 0; y < imgHeight; y++) 
      { 
       var my = [matCi[0][1] * y, matCi[1][1] * y, matCi[2][1] * y]; 

       var offsetY = y * imgWidth; 
       for(var x = 0; x < imgWidth; x++) 
       { 
        var mx = [matCi[0][0] * x, matCi[1][0] * x, matCi[2][0] * x]; 

        var cx = mx[0] + my[0] + mz[0]; 
        var cy = mx[1] + my[1] + mz[1]; 
        var cz = mx[2] + my[2] + mz[2]; 

        var px = Math.round(cx/cz); 
        var py = Math.round(cy/cz); 

        if(px < 0.0 || py < 0.0 || px >= image.width || py >= image.height) 
        { 
         imageData.data[pixelIndex] = 0; 
         imageData.data[pixelIndex + 1] = 255; 
         imageData.data[pixelIndex + 2] = 0; 
         imageData.data[pixelIndex + 3] = 255; 
        } 
        else 
        { 
         var pixelIndex = (offsetY + x) * 4; 
         var pixelIndexSrc = (py * image.width + px) * 4; 

         imageData.data[pixelIndex] = imageDataSrc.data[pixelIndexSrc]; 
         imageData.data[pixelIndex + 1] = imageDataSrc.data[pixelIndexSrc + 1]; 
         imageData.data[pixelIndex + 2] = imageDataSrc.data[pixelIndexSrc + 2]; 
         imageData.data[pixelIndex + 3] = 255; 
        } 
       } 
      } 



      // here to do, image analysis 

     } 

     function getPointRelativePosition() 
     { 
      var pointOrigin = []; 

      for(i = 0; i < 4; i++) 
      { 
       pointOrigin[i] = {x:(points[i].x - marginImage) * image.width/(canvasWidth - marginImage * 2), y:(points[i].y - marginImage) * image.height/(canvasHeight - marginImage * 2)}; 
      } 

      return pointOrigin; 
     } 

     function getPointPosition() 
     { 
      var pointOrigin = []; 

      for(i = 0; i < 4; i++) 
      { 
       pointOrigin[i] = {x:(points[i].x - marginImage)/(canvasWidth - marginImage * 2), y:(points[i].y - marginImage)/(canvasHeight - marginImage * 2)}; 
      } 

      return pointOrigin; 
     } 

     function printPoint(pts) 
     { 
      var result = ''; 


      for(var i = 0; i < 4; i++) 
      { 
       result += "{x:" + pts[i].x + ", y:" + pts[i].y + "},\n"; 
      } 

      console.log(result); 
     } 

     function printMat(mat) 
     { 
      var result = ''; 

      for(var i = 0; i < mat.length; i++) 
      { 
       result += "["; 

       for(var j = 0; j < mat[i].length; j++) 
       { 
        result += mat[i][j] + ", "; 
       } 

       result += "],\n"; 
      } 

      console.log(result); 
     } 

     function canvasResize() 
     { 
      if(canvasWidth != document.body.clientWidth && canvasHeight != document.body.clientHeight) 
      { 
       var transformPoint = getPointPosition(); 

       ratio = image.width/image.height; 
       canvasWidth = document.body.clientWidth; 
       canvasHeight = canvasWidth/ratio; 


       if(document.body.clientHeight < canvasHeight) 
       { 
        canvasHeight = document.body.clientHeight; 
        canvasWidth = canvasHeight * ratio; 
       } 

       canvasLargeur = canvasWidth; 
       canvasLongueur = canvasHeight; 

       if(canvasLargeur < canvasHeight) { 
        canvasLargeur = canvasHeight; 
        canvasLongueur = canvasWidth; 
       } 

       canvasPixelRatio = canvasLargeur/image.width; 

       c.setAttribute("width", canvasWidth); 
       c.setAttribute("height", canvasHeight); 

       marginImage = Math.round(40 * canvasPixelRatio); 

       for(i = 0; i < 4; i++) 
       { 
        points[i].x = transformPoint[i].x * (canvasWidth - marginImage * 2) + marginImage; 
        points[i].y = transformPoint[i].y * (canvasHeight - marginImage * 2) + marginImage; 
       } 

       draw(points); 
      } 
     } 

     c.addEventListener("mousedown", mouseDown, false); 
     c.addEventListener("mouseup", mouseUp, false); 
     c.addEventListener("mousemove", mouseMove, false); 

     c.addEventListener("touchstart", mouseDown, false); 
     c.addEventListener("touchend", mouseUp, false); 
     c.addEventListener("touchmove", mouseMove, false); 

     document.addEventListener("touchstart", cancelDefault, true); 
     document.addEventListener("touchend", cancelDefault, true); 
     document.addEventListener("touchmove", cancelDefault, true); 

     setInterval(canvasResize, 30); 

     draw(points); 

    }; 



</script> 

関連する問題