Recipe
Perspective-correct a photographed document (first pass)
Use when: a document was photographed at an angle instead of scanned flat, and you need a flat, rectangular result
Goal: a warped output image where the document's four corners land exactly on the output rectangle's four corners
Taught in Applied: perspective-correcting a photographed document
Quick recipe
-
1
Locate the (x,y) pixel coordinates of the document's four corners in the source photo. This first pass does it by hand; Chapter 10 automates it once edge and contour detection exist.
Example
The photographed page's corners read approximately (120,80), (940,110), (960,1300), (100,1260): top-left, top-right, bottom-right, bottom-left. Not a rectangle in the photo, since the camera's angle foreshortens the far edge.
Why: every later step depends on these four points being right. An error here spreads through the whole pipeline as a warped-wrong result, not a crash. That makes this the step most worth double-checking by eye.
-
2
Decide the flat output canvas's size, and assign each source corner to the matching destination corner, preserving the same corner order used in Step 1.
Example
An 850\times1100 output canvas gets destination corners (0,0), (850,0), (850,1100), (0,1100): matched top-left/top-right/bottom-right/bottom-left, the same order as Step 1's source corners.
Why: matching order matters. Swapping even one correspondence's position in the list silently produces a mirrored or rotated result instead of an error, since the math has no way to know the labels were meant to line up differently.
-
3
Feed the four correspondences into Section 8's linear system (or call
cv2.getPerspectiveTransformdirectly) to recover the 3\times3 matrix.Example
The four correspondences above solve to a specific H whose bottom row is not [0,0,1]. That confirms a genuine camera-angle warp was present, not just an affine skew a simpler matrix could have captured.
Why: this is the step that actually captures the camera-angle warp, in numbers. Everything before it was measurement, and everything after it is just applying this one matrix.
-
4
Apply H^{-1} as the output-to-source map (Section 5) across every output pixel, sampling with bilinear or bicubic interpolation (Section 6) rather than nearest-neighbor.
Example
The 850\times1100 canvas is filled pixel by pixel. A pixel near the photo's foreshortened far edge samples from a wider spread of nearby source pixels than a pixel near the near edge does. That directly reflects how much the camera's angle compressed that part of the photo.
Why: skipping inverse mapping in favor of forward mapping would leave holes in the output (Section 5). That's exactly the failure mode this chapter's tools exist to avoid.
-
5
Check that the four corners now land exactly on the output rectangle and the page edges read straight. Note that the result is still a raw grayscale or color warp, not yet a clean scan.
Example
The warped output has straight, rectangular edges, but keeps patchy lighting and a slightly gray background. Chapter 10's thresholding step is what turns this into a clean black-and-white scan.
Why: naming what's still missing, rather than showing this as a finished scanner, is the honest scope this section promised in its own title.
Common mistakes
- Picking source corners in a different turning order than destination corners (clockwise for one, counterclockwise for the other). This silently mirrors or rotates the result.
- Using nearest-neighbor interpolation for the final warp. This leaves visibly jagged text edges where bilinear or bicubic would have stayed smooth.
- Adding a fifth pair of corners "to be safe": four correspondences pin down a homography exactly (Section 8). A fifth over-determines the system and needs least-squares instead of an exact solve.