Want to straighten or crop a part of an image just by clicking on it? Whether it’s a credit card, document, or anything skewed — you can use Python to perform a perspective warp with just 4 mouse clicks.
In this tutorial, I’ll walk you through how to build a perspective warp tool in Python using OpenCV, from scratch. Even if you’re a beginner, don’t worry — I’ll explain everything line-by-line.
🧠 What You’ll Learn
- How to use OpenCV mouse click events
- How to extract a region from an image using a perspective transform
- How to display and warp your clicked area into a flat rectangle
🔍 Why Use Perspective Warp in Python?
Let’s say you take a photo of a card or paper from an angle. The edges look warped. A perspective warp straightens that — like turning a photo taken at an angle into a neat top-down view.
🧠 Use cases:
- Scanning IDs or documents
- Preprocessing images for OCR
- Fixing distorted images
🧰 What You Need
Before we begin, make sure you have these installed:
pip install opencv-python numpy
Also, save an image named cards.jpg in the same folder. This is the image you’ll click on.
🧑💻 Step-by-Step Code Breakdown
Let’s write the whole script step by step.
🔹 1. Import Libraries
import cv2
import numpy as np
We’ll use:
cv2for image display, mouse events, and transformations.numpyfor storing coordinates.
🔹 2. Setup Variables
circles = np.zeros((4, 2), np.int32)
counter = 0
We’ll store 4 clicked points in a NumPy array and count how many clicks we’ve made.
🔹 3. Create the Mouse Event Function
def mousePoints(event, x, y, flags, params):
global counter
if event == cv2.EVENT_LBUTTONDOWN and counter < 4:
circles[counter] = x, y
counter += 1
print("Clicked Points:", circles)
Each time you click, the point is saved and printed.
🔹 4. Load the Image
img = cv2.imread('cards.jpg')
This loads the image you’ll be clicking on. It must be in the same folder.
🔹 5. Main Display Loop
while True:
Keeps refreshing the image window so it’s interactive.
🔹 6. Warp After 4 Clicks
if counter == 4:
width, height = 250, 350
pts1 = np.float32([circles[0], circles[1], circles[2], circles[3]])
pts2 = np.float32([[0, 0], [width, 0], [0, height], [width, height]])
matrix = cv2.getPerspectiveTransform(pts1, pts2)
imgOutput = cv2.warpPerspective(img, matrix, (width, height))
cv2.imshow("Warped Output", imgOutput)
Once all 4 points are clicked, OpenCV:
- Computes a transformation matrix.
- Warps the region to a clean, rectangular view.
🔹 7. Draw Circles on Points
for i in range(counter):
cv2.circle(img, (circles[i][0], circles[i][1]), 5, (0, 255, 0), cv2.FILLED)
Just some helpful green dots to show where you’ve clicked.
🔹 8. Show Image & Handle Clicks
cv2.imshow("Original Image", img)
cv2.setMouseCallback("Original Image", mousePoints)
cv2.waitKey(1)
The real-time magic happens here.
🧾 Final Full Code: warp_tool.py
import cv2
import numpy as np
circles = np.zeros((4, 2), np.int32)
counter = 0
def mousePoints(event, x, y, flags, params):
global counter
if event == cv2.EVENT_LBUTTONDOWN and counter < 4:
circles[counter] = x, y
counter += 1
print("Clicked Points:", circles)
img = cv2.imread('cards.jpg')
while True:
if counter == 4:
width, height = 250, 350
pts1 = np.float32([circles[0], circles[1], circles[2], circles[3]])
pts2 = np.float32([[0, 0], [width, 0], [0, height], [width, height]])
matrix = cv2.getPerspectiveTransform(pts1, pts2)
imgOutput = cv2.warpPerspective(img, matrix, (width, height))
cv2.imshow("Warped Output", imgOutput)
for i in range(counter):
cv2.circle(img, (circles[i][0], circles[i][1]), 5, (0, 255, 0), cv2.FILLED)
cv2.imshow("Original Image", img)
cv2.setMouseCallback("Original Image", mousePoints)
cv2.waitKey(1)
🧪 How to Run It
- Save the script as
warp_tool.py - Place
cards.jpgin the same folder. - Open terminal, navigate to folder, and run:
python warp_tool.py
- Click 4 corners on the image.
- The warped version will appear.
📌 Common Questions (FAQs)
❓ Can I use this with any image?
Yes! As long as it has 4 sides and you can identify corners clearly.
❓ What if I want a bigger output?
Change the values of width and height.
❓ Can I save the output?
Yes! Just add:
cv2.imwrite("output.jpg", imgOutput)
🧩 Bonus: Expand This Project
- Add a reset button
- Allow dynamic output size
- Drag-and-drop interface (using Tkinter)
Check out How to Build a Currency Converter App in Streamlit if you want to build GUI-based tools!
🏁 Conclusion
Performing a perspective warp in Python using OpenCV and mouse clicks is a powerful trick to have in your image-processing toolkit.
With just a few lines of code, you can turn any angled photo into a clean, scanned-style image.