2017-05-04 1 views
0

다른 이미지를 추출하기 위해 행렬로 픽셀 조작을 연습하고 싶습니다. 나는의 콘텐츠를 찾을 왼쪽 이미지 'L'나는 4 점 이미지 주위와 오른쪽 이미지 'R'에 장소가와 https://www.noelshack.com/2017-18-1493893008-capture-2.png이미지 변형 행렬

:

내가 CSS를 변환 행렬로 한 일입니다 변환.

나는 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)입니다. 이 계산을 수행합니다. 0,0 위치 이처럼

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

:

M * P = P' 

P는 R 화상 P의 화소 위치 인 '화소

P 매트릭스처럼 정의되는 L 화상의 위치는 , 나는 이것을한다 :

[[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 또는 역방향 R-> L 인 경우이 매트릭스입니까? 2D 변환을 위해 행렬이 3x3 대신 4x4 인 이유는 무엇입니까? 시프트 구성 요소 (12/-17?)가 너무 작게 보입니다. – MBo

+0

상호 참조 : 주어진 네 개의 점과 그 이미지가있는 행렬을 찾는 단계는 https://math.stackexchange.com/a/339033/35416을 참조하십시오. 대답과 코멘트에는 작동하는 JavaScript/CSS 데모가 포함되어 있습니다. – MvG

답변

0

이들은 동질 좌표계입니다. 그래서 [x1, y1, z1, 1]의 일부를 입력하면 [x2, y2, z2, w2]를 얻을 수 있습니다. 그러나 실제 위치는 [x2/w2, y2/w2, z2/w2]입니다. 마지막 좌표로 나눕니다.

그러나 예상 한 결과로 이어지지는 않습니다. 행렬을 그 부속 장치 (또는 등가 적으로 역행렬)로 대체하거나 행렬을 대체하지 않습니다. 이 두 가지 방법 모두 잘못하기 쉽기 때문에 실제로 어떤 버전이 필요한지에 대해 너무 많은 생각을 들이지 않고도 네 가지 대안을 모두 시도해보십시오 (조화를 사용하거나 사용하지 않은 상태에서 조화를 사용하거나 사용하지 않은 상태에서) 다량의 사소한 문제가 해결됩니다 .

하지만 내 것이 아닙니다. 그래서 제 다음으로 가장 좋은 방법은 이미지의 일부 구석에서 측정 된 좌표입니다. CSS 속성 transform-origin은 초기 값이 50% 50% 0이므로 좌표계의 원점이 실제로 객체의 중심에있게됩니다.

실제로 HTML과 CSS를 공유하면이 가정을 확인할 수 있습니다. 이제 이것이 당신에게 적용되는지 확인해야합니다. 내가 마지막으로 a projective image transformation demoanswer a question about finding the transform으로 만들었을 때 나는 이러한 문제를 피하기 위해 고의적으로 transform-origin: 0 0; (그리고 이것의 여러 공급 업체 접두어 버전)을 설정했음을 기억합니다.

0

감사합니다. MvG. 내가 아이디어를 제공하기위한 픽셀 관련 L < -R

내 코드를 공유 찾을 수있는 C 행렬을 반전해야

나는 귀하의 링크를 따라 나는 [https://math.stackexchange.com/a/339033] 한 가지를 원하는 것을 찾을 수 당신은 당신은 기능 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> 

관련 문제