Cropper
What is Cropper?
Cropper enables users to retrieve the coordinates of cropped images from a document through our APIs.

Receipt cropping and background removal
How it Works
The cropper feature can be used on any API on the prediction route:
https://api.mindee.net/v1/products/<account_name>/<api_name>/<api_version>/predict?cropper=true
?cropper=true
is the additional parameter to add to your API calls.
Cropper Output
The cropper results are located at the page level when retrieving document prediction. The cropper results are returned in the following JSON object document.inference.pages[].extras.cropper.cropping[].xxxxxx
. Most of the time, taking the first element of the cropper output is sufficient for most use case.
The results show the polygon vertices at the page level, for each possible cropped document within the image:
- bounding_box: straight rectangle (always inside canvas).
- rectangle: rectangle that may be oriented (can go beyond the canvas, ie. vertices coordinate < 0 and > 1).
- quadrangle: free polygon with 4 vertices (always inside canvas).
- polygon: free polygon with up to 30 vertices (always inside canvas).
The vertices format are a list of (x, y) relative coordinates to your document, always in clockwise order. Starting vertex may not be fixed (depends if this is a rectangle or a free polygon).
Example:
...
"rectangle": [
[0, 0.996],
[0.002, -0.002],
[0.996, 0],
[0.994, 0.998]
]
...
Orientation
The coordinates returned by the cropper take in consideration the rotation of the document. You can find this information in
document.inference.pages[].orientation
in the form of clockwise degrees. The value is the clockwise rotation to apply on the source page document to get the page upright.
Example With Receipts V3
Using this sample receipt document we append the cropper additional param ?cropper=true
to the receipts API URL.
curl -X POST
https://api.mindee.net/v1/products/mindee/expense_receipts/v3/predict?cropper=true
-H 'Authorization: Token my-token'
-F [email protected]/path/to/your/file.png
import requests
url = "https://api.mindee.net/v1/products/mindee/expense_receipts/v3/predict?cropper=true"
with open("/path/to/my/file", "rb") as myfile:
files = {"document": myfile}
headers = {"Authorization": "Token my-api-key-here"}
response = requests.post(url, files=files, headers=headers)
print(response.text)
// works for NODE > v10
const axios = require('axios');
const fs = require("fs");
const FormData = require('form-data')
async function makeRequest() {
let data = new FormData()
data.append('document', fs.createReadStream('./file.jpg'))
const config = {
method: 'POST',
url: 'https://api.mindee.net/v1/products/mindee/expense_receipts/v3/predict?cropper=true',
headers: {
'Authorization':'Token my-api-key-here',
...data.getHeaders()
},
data
}
try {
let response = await axios(config)
console.log(response.data);
} catch (error) {
console.log(error)
}
}
makeRequest()
# tested with Ruby 2.5
require 'uri'
require 'net/http'
require 'net/https'
require 'mime/types'
url = URI("https://api.mindee.net/v1/products/mindee/expense_receipts/v3/predict?cropper=true")
file = "/path/to/your/file.png"
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Token my-api-key-here'
request.set_form([['document', File.open(file)]], 'multipart/form-data')
response = http.request(request)
puts response.read_body
<form onsubmit="mindeeSubmit(event)" >
<input type="file" id="my-file-input" name="file" />
<input type="submit" />
</form>
<script type="text/javascript">
const mindeeSubmit = (evt) => {
evt.preventDefault()
let myFileInput = document.getElementById('my-file-input');
let myFile = myFileInput.files[0]
if (!myFile) { return }
let data = new FormData();
data.append("document", myFile, myFile.name);
let xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://api.mindee.net/v1/products/mindee/expense_receipts/v3/predict?cropper=true");
xhr.setRequestHeader("Authorization", "Token my-api-key-here");
xhr.send(data);
}
</script>
Our result shows the different polygon vertices (bounding_box
, rectangle
, quadrangle
, polygon
) at the page level.
{
...
"document": {
"id": "62c6198c-e0a8-4ee7-b922-7b5b98bedb79",
"inference": {
"extras": {},
"finished_at": "2022-03-25T16:17:18+00:00",
"is_rotation_applied": true,
"pages": [
{
"extras": {
"cropper": {
"cropping": [
{
"bounding_box": [
[0.121, 0],
[0.787, 0],
[0.787, 0.998],
[0.121, 0.998]
],
"polygon": [
[0.152, 0.416],
[0.16, 0.186],
[0.172, 0.02],
[0.211, 0.006],
[0.357, 0.006],
[0.592, 0.006],
[0.656, 0.023],
[0.775, 0.043],
[0.789, 0.055],
[0.756, 0.549],
[0.756, 0.637],
[0.736, 0.955],
[0.719, 0.994],
[0.607, 0.996],
[0.197, 0.996],
[0.131, 0.994],
[0.123, 0.982],
[0.125, 0.855],
[0.139, 0.668],
[0.139, 0.584]
],
"quadrangle": [
[0.173, 0],
[0.786, 0.012],
[0.737, 0.994],
[0.122, 0.996]
],
"rectangle": [
[0.172, -0.019],
[0.785, 0.012],
[0.735, 1.027],
[0.121, 0.996]
]
}
]
}
},
"id": 0,
"orientation": {
"value": 0
},
...
}
]
}
}
}
Questions?
Join our Slack
Updated 6 months ago