Online OpenCV Compiler

Run OpenCV (cv2) code in your browser. Convert colours, blur, detect edges, draw shapes, find contours, resize and rotate images.

Python
# Basic image processing using OpenCV

import cv2
import requests
import numpy as np
import matplotlib.pyplot as plt
from io import BytesIO

# Fetch the image from the URL using requests
url = 'https://images.unsplash.com/photo-1444464666168-49d633b86797?w=800&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MXx8YmlyZHxlbnwwfHwwfHx8Mg%3D%3D'
response = requests.get(url)
image = np.asarray(bytearray(response.content), dtype="uint8")
image = cv2.imdecode(image, cv2.IMREAD_COLOR)

# Convert the image to grayscale
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# Apply a Gaussian blur to the image
blurred_image = cv2.GaussianBlur(gray_image, (5, 5), 0)

# Detect edges using the Canny edge detection algorithm
edges = cv2.Canny(blurred_image, 100, 200)

# Display the original and processed images
plt.figure(figsize=(10, 7))

plt.subplot(2, 2, 1)
plt.title('Original Image')
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
plt.axis('off')

plt.subplot(2, 2, 2)
plt.title('Grayscale Image')
plt.imshow(gray_image, cmap='gray')
plt.axis('off')

plt.subplot(2, 2, 3)
plt.title('Blurred Image')
plt.imshow(blurred_image, cmap='gray')
plt.axis('off')

plt.subplot(2, 2, 4)
plt.title('Edge Detection')
plt.imshow(edges, cmap='gray')
plt.axis('off')

plt.tight_layout()
plt.show()

OpenCV is a computer vision library written in C++, and cv2 is its Python interface. It reads and writes images, filters and transforms them, and finds edges, shapes and features. Every image is a NumPy array. People use it to process photos, detect faces and objects, and analyse video. This page is an online OpenCV compiler: the code runs in your browser, so you can try it without installing anything. Run the example first, then paste any snippet below into a new cell to try it.

What the example does

requests.get() downloads a photo of a kingfisher, and cv2.imdecode() decodes the JPEG bytes into a (534, 800, 3) array of uint8 values: 534 rows, 800 columns and three colour channels. OpenCV stores the channels in blue, green, red (BGR) order. cv2.cvtColor() with cv2.COLOR_BGR2GRAY turns the photo into a single-channel grey image. cv2.GaussianBlur() smooths it with a 5 by 5 kernel, and the 0 tells OpenCV to work out the blur strength from the kernel size. cv2.Canny() then marks edges with two thresholds. Gradients above 200 become edges, and weaker ones down to 100 are kept only where they connect to a strong edge. Without the blur, it would mark about twice as many pixels. The result contains only 0 and 255. matplotlib draws the four images in a 2 by 2 grid. It expects RGB, so the colour photo goes through cv2.COLOR_BGR2RGB first.

Draw shapes and save an image

Drawing functions change the array in place. Points are (x, y), colours are (blue, green, red), and a thickness of -1 fills the shape. cv2.imwrite() saves the result as shapes.png for the next snippets:

import cv2
import numpy as np
import matplotlib.pyplot as plt

canvas = np.full((300, 400, 3), 255, dtype=np.uint8)   # 300 rows, 400 columns, white

cv2.rectangle(canvas, (30, 40), (150, 160), (255, 0, 0), -1)      # blue square
cv2.circle(canvas, (270, 100), 60, (0, 0, 255), -1)               # red circle
triangle = np.array([[60, 270], [140, 190], [220, 270]], np.int32)
cv2.fillPoly(canvas, [triangle], (0, 160, 0))                     # green triangle
cv2.putText(canvas, "OpenCV", (240, 250), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)
cv2.imwrite("shapes.png", canvas)

plt.imshow(cv2.cvtColor(canvas, cv2.COLOR_BGR2RGB))
plt.axis("off")
plt.show()

The next two snippets read shapes.png, so run this one first.

Find and count shapes

cv2.threshold() turns the image into a black and white mask, cv2.findContours() traces each white region, and cv2.approxPolyDP() reduces an outline to its corners:

import cv2

img = cv2.imread("shapes.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, mask = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)   # shapes white, background black
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
print(len(contours), "outlines found")

for contour in contours:
    area = cv2.contourArea(contour)
    if area < 1000:          # skip the letters
        continue
    corners = cv2.approxPolyDP(contour, 0.02 * cv2.arcLength(contour, True), True)
    x, y, w, h = cv2.boundingRect(contour)
    print(f"{len(corners)} corners, area {area:.0f}, box at x={x}, y={y}, {w}x{h}")

The six letters of "OpenCV" are outlines too, so nine are found. To use your own photo, click Mount folder in the sidebar's Data tab (Chrome or Edge on a computer), choose the folder it is in, and read it by name with cv2.imread(). Add files does not take images.

Resize, crop, flip and rotate

cv2.resize() takes the new size as (width, height), but array shapes and slices are (rows, columns). cv2.getRotationMatrix2D() builds a rotation, counterclockwise for a positive angle, and cv2.warpAffine() applies it:

import cv2
import matplotlib.pyplot as plt

img = cv2.imread("shapes.png")
print(img.shape)                             # (rows, columns, channels)

small = cv2.resize(img, (200, 150))          # (width, height)
cropped = img[40:161, 30:151]                # rows first, then columns
flipped = cv2.flip(img, 1)                   # 1 mirrors left to right
h, w = img.shape[:2]
matrix = cv2.getRotationMatrix2D((w / 2, h / 2), 30, 1.0)   # centre, angle, scale
rotated = cv2.warpAffine(img, matrix, (w, h), borderValue=(255, 255, 255))
print(small.shape, cropped.shape, flipped.shape, rotated.shape)

plt.imshow(cv2.cvtColor(rotated, cv2.COLOR_BGR2RGB))
plt.axis("off")
plt.show()

The rotated image keeps its size, so corners outside the frame are cut off.

Good to know

  • cv2.imshow() and cv2.waitKey() do not work here: this OpenCV build has no GUI support. Either call stops Python with a fatal error that try/except cannot catch, and no more code runs until you reload the page. Show images with plt.imshow() instead.
  • cv2.imread() does not raise an error for a missing file. It prints a warning and returns None, so check the result.
  • On uint8 images, cv2.add() stops at 255, while NumPy's + wraps around: 250 + 10 gives 4.