How to Do a Perspective Warp in Python with Just 4 Mouse Clicks

Learn how to perform a perspective warp in Python using OpenCV and mouse clicks. Full beginner-friendly tutorial with step-by-step code.

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:

  • cv2 for image display, mouse events, and transformations.
  • numpy for 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

  1. Save the script as warp_tool.py
  2. Place cards.jpg in the same folder.
  3. Open terminal, navigate to folder, and run:
python warp_tool.py
  1. Click 4 corners on the image.
  2. 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.


🔗 Useful Links

Posted by Ananya Rajeev

Ananya Rajeev is a Kerala-born data scientist and AI enthusiast who simplifies generative and agentic AI for curious minds. B.Tech grad, code lover, and storyteller at heart.