2012-10-31 19 views
9

Tôi đang cố gắng thực hiện một phối cảnh chuyển đổi trên một bitmap mà tôi chụp qua máy ảnh. Người dùng điều chỉnh một tứ giác (như được mô tả bởi hộp màu trắng) xung quanh một vật thể hình chữ nhật. Sau đó, tôi cố chuyển đổi hình ảnh này thành hình chữ nhật bằng cách sử dụng mã bên dưới:Cắt một chuyển đổi phối cảnh của hình ảnh trên Android

public static Bitmap perspectiveTransformation(Bitmap bitmap,BoundingQuad boundingQuad) 
{ 
    Matrix matrix = new Matrix(); 
    float[] dst = new float[] { 
      0, 
      0, 
      bitmap.getWidth(), 
      0, 
      bitmap.getWidth(), 
      bitmap.getHeight(), 
      0, 
      bitmap.getHeight() 
    }; 
    float[] src = new float[] { 
      boundingQuad.topLeft.x, 
      boundingQuad.topLeft.y, 
      boundingQuad.topRight.x, 
      boundingQuad.topRight.y, 
      boundingQuad.bottomRight.x, 
      boundingQuad.bottomRight.y, 
      boundingQuad.bottomLeft.x, 
      boundingQuad.bottomLeft.y 
    }; 
    matrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1); 
    return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); 
} 

Tuy nhiên, hình ảnh kết quả của tôi chứa dữ liệu hình ảnh nằm ngoài ranh giới của quad. Điều này sẽ được chấp nhận nếu tôi có thể tìm ra những gì các tọa độ của quad là sau khi chuyển đổi vì vậy tôi có thể cắt kết quả nhưng tôi hoàn toàn không có ý tưởng làm thế nào để làm điều đó.

Bất kỳ trợ giúp nào sẽ được đánh giá rất cao trong việc tìm ra tọa độ của tứ giác sau khi chuyển đổi hoặc lý tưởng là tìm cách ngăn tình trạng này xảy ra ngay từ đầu.

Input:

http://i.stack.imgur.com/33RfN.png

Output:

http://i.stack.imgur.com/zWFvA.png

+0

bạn đã tìm thấy một giải pháp? Tôi có cùng một vấn đề. –

+0

@ romain-guy có lẽ bạn có một gợi ý cho vấn đề đó? –

Trả lời

-2

Sau khi bạn tạo Bitmap hình ảnh mới của bạn, bạn có thể gọi Android được xây dựng trong chức năng cây trồng bằng cách xây dựng một 'cây' ý định và gọi điện cho nó, ví dụ:

Intent cropIntent = new Intent("com.android.camera.action.CROP"); 

// Put in 'Extras' here to build the intent 

// Start the activity. It will be handled by returning data to onActivityResult 
startActivityForResult(cropIntent, PIC_CROP); // PIC_CROP is just an arbitrary tag name. 

Thông tin chi tiết về cắt xén hình ảnh trong Android có thể đạt được từ here.

Bạn cũng sẽ cần phải thêm như sau trong file manifest của ứng dụng của bạn để làm việc này:

<uses-feature android:name="android.hardware.camera" ></uses-feature> 
<uses-permission android:name="android.permission.CAMERA" /> 
3

tôi đã cùng một vấn đề và giải quyết nó bằng cách tìm tọa độ của hình chữ nhật sau khi chuyển đổi.

Để tìm các tọa độ này, bạn phải hiểu những gì đang diễn ra. Ma trận xác định phép biến đổi phối cảnh, được đưa ra bởi 4 điểm cạnh của tứ giác và các điểm tương ứng. Bạn đã thực hiện điều này với mã sau:

Matrix matrix = new Matrix(); 
float[] dst = new float[] { 
     0, 
     0, 
     bitmap.getWidth(), 
     0, 
     bitmap.getWidth(), 
     bitmap.getHeight(), 
     0, 
     bitmap.getHeight() 
}; 
float[] src = new float[] { 
     boundingQuad.topLeft.x, 
     boundingQuad.topLeft.y, 
     boundingQuad.topRight.x, 
     boundingQuad.topRight.y, 
     boundingQuad.bottomRight.x, 
     boundingQuad.bottomRight.y, 
     boundingQuad.bottomLeft.x, 
     boundingQuad.bottomLeft.y 
}; 
matrix.setPolyToPoly(src, 0, dst, 0, src.length >> 1); 

Điều này có nghĩa là (ví dụ) điểm trên cùng bên trái của quad được chuyển thành điểm (0,0). Bạn có thể xác minh điều này bằng cách áp dụng ma trận cho các điểm và kiểm tra các giá trị kết quả. Để áp dụng ma trận, bạn có thể sử dụng phương thức mapPoints(...). Ma trận chuyển đổi được xác định hoạt động tốt. Các (ở cái nhìn đầu tiên) hành vi kỳ lạ của kết quả chuyển đổi này từ việc tạo ra các bitmap:

return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); 

các bitmap kết quả có vẻ là sai, bởi vì một số điểm (ví dụ như tất cả các điểm đến ở bên trái của từ trên điểm bên trái của quad) được chuyển thành tọa độ âm và nếu bạn muốn vẽ thứ gì đó vào bitmap thì tọa độ phải dương. Bởi vì điều này các điểm chuyển đổi được thay đổi và dẫn đến tọa độ kỳ lạ của các điểm chuyển đổi trong bitmap.

Để kết luận: Các điểm được chuyển chính xác sang tọa độ mới, nhưng không thể hiển thị và vì điều này chúng được dịch chuyển và tọa độ dịch chuyển của các điểm được chuyển đổi trong bitmap không phải là tọa độ, được xác định trong ma trận biến đổi.

Để giải quyết vấn đề này và nhận được tọa độ thích hợp của các điểm được chuyển đổi trong bitmap, bạn phải tính giá trị của ca. Sự dịch chuyển bao gồm giá trị x và giá trị y.

Để tính giá trị x, tôi đã chuyển giá trị x của điểm trên cùng bên trái và giá trị x của điểm dưới bên trái của hình ảnh gốc với ma trận được xác định trước đó. Điểm trên cùng bên trái hoặc điểm dưới bên trái được chuyển sang ranh giới bên trái của bitmap kết quả và vì điều này giá trị x của tọa độ bitmap của điểm này bằng 0 và phủ định (vì x- giá trị cần phải dương) x-giá trị của các tọa độ được chuyển đổi là giá trị x của ca. Điểm, được chuyển thành ranh giới bên trái của bitmap kết quả là điểm có giá trị x cực đại bị loại bỏ. Do đó, giá trị x của ca là giá trị lớn nhất của các giá trị x được phủ định của điểm trên cùng bên trái và dưới bên trái.

Để tính giá trị y, tôi đã chuyển giá trị y của điểm trên cùng bên trái và giá trị y của điểm trên cùng bên phải của hình ảnh gốc, bởi vì đây là các điểm có thể được chuyển đổi thành đầu ranh giới của bitmap kết quả và giá trị y của điểm được chuyển đổi bằng 0 trong bitmap kết quả. Bằng cách lấy lại tối đa các giá trị được phủ định của các giá trị y đã chuyển đổi, bạn sẽ nhận được giá trị y của ca.

Mã kết quả trông như thế này:

float[] mappedTL = new float[] { 0, 0 }; 
    matrix.mapPoints(mappedTL); 
    int maptlx = Math.round(mappedTL[0]); 
    int maptly = Math.round(mappedTL[1]); 

    float[] mappedTR = new float[] { bitmap.getWidth(), 0 }; 
    matrix.mapPoints(mappedTR); 
    int maptrx = Math.round(mappedTR[0]); 
    int maptry = Math.round(mappedTR[1]); 

    float[] mappedLL = new float[] { 0, bitmap.getHeight() }; 
    matrix.mapPoints(mappedLL); 
    int mapllx = Math.round(mappedLL[0]); 
    int maplly = Math.round(mappedLL[1]); 

    int shiftX = Math.max(-maptlx, -mapllx); 
    int shiftY = Math.max(-maptry, -maptly); 

    Bitmap resultBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); 
    return Bitmap.createBitmap(resultBitmap, shiftX, shiftY, bitmap.getWidth(), bitmap.getHeight(), null, true); 
Các vấn đề liên quan