xbe.at

Python / Python for ML and AI

Mastering Bitwise Operations in OpenCV with Python

7 min read, 14 sections

Contents
  1. Introduction to Bitwise Operations in OpenCV
  2. Bitwise AND Operation
  3. Bitwise OR Operation
  4. Bitwise XOR Operation
  5. Bitwise NOT Operation
  6. Creating Complex Masks
  7. Real-Life Example: Logo Watermarking
  8. Bit Manipulation for Image Encryption
  9. Bitwise Operations for Feature Extraction
  10. Optimizing Bitwise Operations
  11. Bitwise Operations for Image Segmentation
  12. Bitwise Operations for Image Compositing
  13. Real-Life Example: Document Scanner
  14. Additional Resources

Introduction to Bitwise Operations in OpenCV

Bitwise operations are fundamental tools in image processing and computer vision. In OpenCV, these operations allow us to manipulate individual bits of an image, enabling tasks such as masking, feature extraction, and image composition. This slideshow will explore how to master bitwise operations using OpenCV and Python.

import numpy as np

# Create two sample images
img1 = np.zeros((200, 200), dtype=np.uint8)
img1[50:150, 50:150] = 255

img2 = np.zeros((200, 200), dtype=np.uint8)
cv2.circle(img2, (100, 100), 75, 255, -1)

# Display the images
cv2.imshow('Image 1', img1)
cv2.imshow('Image 2', img2)
cv2.waitKey(0)
cv2.destroyAllWindows()

Bitwise AND Operation

The bitwise AND operation compares each bit of two images and returns 1 only if both bits are 1. This operation is useful for masking and extracting specific regions of interest in an image.

result_and = cv2.bitwise_and(img1, img2)

# Display the result
cv2.imshow('Bitwise AND', result_and)
cv2.waitKey(0)
cv2.destroyAllWindows()

Bitwise OR Operation

The bitwise OR operation returns 1 if at least one of the corresponding bits in the two images is 1. This operation is useful for combining features from multiple images.

result_or = cv2.bitwise_or(img1, img2)

# Display the result
cv2.imshow('Bitwise OR', result_or)
cv2.waitKey(0)
cv2.destroyAllWindows()

Bitwise XOR Operation

The bitwise XOR (exclusive OR) operation returns 1 if the corresponding bits in the two images are different. This operation can be used to find differences between images or create interesting visual effects.

result_xor = cv2.bitwise_xor(img1, img2)

# Display the result
cv2.imshow('Bitwise XOR', result_xor)
cv2.waitKey(0)
cv2.destroyAllWindows()

Bitwise NOT Operation

The bitwise NOT operation inverts all bits in an image, changing 0s to 1s and vice versa. This operation is useful for creating inverse masks or negative images.

result_not_img1 = cv2.bitwise_not(img1)
result_not_img2 = cv2.bitwise_not(img2)

# Display the results
cv2.imshow('Bitwise NOT (Image 1)', result_not_img1)
cv2.imshow('Bitwise NOT (Image 2)', result_not_img2)
cv2.waitKey(0)
cv2.destroyAllWindows()

Creating Complex Masks

Bitwise operations can be combined to create complex masks for advanced image processing tasks. Let's create a mask that isolates the intersection of two shapes.

mask = cv2.bitwise_and(img1, img2)
inverse_mask = cv2.bitwise_not(mask)

# Apply the mask to an image
original = cv2.imread('image.jpg', cv2.IMREAD_COLOR)
masked_image = cv2.bitwise_and(original, original, mask=mask)
background = cv2.bitwise_and(original, original, mask=inverse_mask)

# Combine the masked image and background
result = cv2.add(masked_image, background)

cv2.imshow('Complex Masking Result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

Real-Life Example: Logo Watermarking

Bitwise operations can be used to add watermarks to images. This example demonstrates how to overlay a logo on an image using bitwise operations.

main_image = cv2.imread('main_image.jpg')
logo = cv2.imread('logo.png', cv2.IMREAD_UNCHANGED)

# Create a region of interest (ROI) for the logo
rows, cols, _ = logo.shape
roi = main_image[-rows-10:-10, -cols-10:-10]

# Create a mask and its inverse
logo_gray = cv2.cvtColor(logo, cv2.COLOR_BGR2GRAY)
_, mask = cv2.threshold(logo_gray, 10, 255, cv2.THRESH_BINARY)
mask_inv = cv2.bitwise_not(mask)

# Black-out the area of logo in ROI
img_bg = cv2.bitwise_and(roi, roi, mask=mask_inv)

# Take only region of logo from logo image
logo_fg = cv2.bitwise_and(logo[:,:,:3], logo[:,:,:3], mask=mask)

# Add logo to ROI and modify the main image
dst = cv2.add(img_bg, logo_fg)
main_image[-rows-10:-10, -cols-10:-10] = dst

cv2.imshow('Watermarked Image', main_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

Bit Manipulation for Image Encryption

Bitwise operations can be used for simple image encryption. This example demonstrates how to use XOR operation to encrypt and decrypt an image.

    # Ensure the key is the same size as the image
    key = cv2.resize(key, (image.shape[1], image.shape[0]))
    
    # Perform XOR operation
    result = cv2.bitwise_xor(image, key)
    return result

# Load an image and create a random key
image = cv2.imread('secret_image.jpg', cv2.IMREAD_GRAYSCALE)
key = np.random.randint(0, 256, image.shape, dtype=np.uint8)

# Encrypt the image
encrypted = encrypt_decrypt(image, key)

# Decrypt the image
decrypted = encrypt_decrypt(encrypted, key)

# Display results
cv2.imshow('Original', image)
cv2.imshow('Encrypted', encrypted)
cv2.imshow('Decrypted', decrypted)
cv2.waitKey(0)
cv2.destroyAllWindows()

Bitwise Operations for Feature Extraction

Bitwise operations can be used to extract specific color channels or features from an image. This example demonstrates how to isolate red objects in an image.

image = cv2.imread('colorful_objects.jpg')

# Split the image into its BGR channels
b, g, r = cv2.split(image)

# Create a mask to isolate red objects
red_mask = cv2.bitwise_and(cv2.threshold(r, 100, 255, cv2.THRESH_BINARY)[1],
                           cv2.bitwise_not(cv2.threshold(b, 100, 255, cv2.THRESH_BINARY)[1]))
red_mask = cv2.bitwise_and(red_mask,
                           cv2.bitwise_not(cv2.threshold(g, 100, 255, cv2.THRESH_BINARY)[1]))

# Apply the mask to the original image
red_objects = cv2.bitwise_and(image, image, mask=red_mask)

cv2.imshow('Original Image', image)
cv2.imshow('Red Objects', red_objects)
cv2.waitKey(0)
cv2.destroyAllWindows()

Optimizing Bitwise Operations

When working with large images or real-time applications, optimizing bitwise operations becomes crucial. This slide demonstrates how to use NumPy's vectorized operations for faster processing.


# Create large images for testing
large_img1 = np.random.randint(0, 256, (2000, 2000), dtype=np.uint8)
large_img2 = np.random.randint(0, 256, (2000, 2000), dtype=np.uint8)

# OpenCV bitwise AND
start_time = time.time()
opencv_result = cv2.bitwise_and(large_img1, large_img2)
opencv_time = time.time() - start_time

# NumPy bitwise AND
start_time = time.time()
numpy_result = np.bitwise_and(large_img1, large_img2)
numpy_time = time.time() - start_time

print(f"OpenCV time: {opencv_time:.4f} seconds")
print(f"NumPy time: {numpy_time:.4f} seconds")
print(f"Speed-up: {opencv_time / numpy_time:.2f}x")

Bitwise Operations for Image Segmentation

Bitwise operations can be combined with thresholding techniques to perform image segmentation. This example demonstrates how to segment an image based on color information.

image = cv2.imread('fruits.jpg')

# Convert to HSV color space
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

# Define color range for segmentation (e.g., yellow)
lower_yellow = np.array([20, 100, 100])
upper_yellow = np.array([30, 255, 255])

# Create a mask using color thresholding
mask = cv2.inRange(hsv, lower_yellow, upper_yellow)

# Apply the mask to the original image
segmented = cv2.bitwise_and(image, image, mask=mask)

cv2.imshow('Original Image', image)
cv2.imshow('Segmented Image', segmented)
cv2.waitKey(0)
cv2.destroyAllWindows()

Bitwise Operations for Image Compositing

Bitwise operations are powerful tools for image compositing. This example demonstrates how to blend two images using a mask created with bitwise operations.

background = cv2.imread('background.jpg')
foreground = cv2.imread('foreground.png', cv2.IMREAD_UNCHANGED)

# Separate the alpha channel
foreground_rgb = foreground[:,:,:3]
alpha = foreground[:,:,3]

# Create a binary mask from the alpha channel
_, mask = cv2.threshold(alpha, 0, 255, cv2.THRESH_BINARY)

# Create the inverse mask
mask_inv = cv2.bitwise_not(mask)

# Resize foreground to fit background
foreground_resized = cv2.resize(foreground_rgb, (background.shape[1], background.shape[0]))
mask_resized = cv2.resize(mask, (background.shape[1], background.shape[0]))
mask_inv_resized = cv2.resize(mask_inv, (background.shape[1], background.shape[0]))

# Bitwise operations for compositing
background_masked = cv2.bitwise_and(background, background, mask=mask_inv_resized)
foreground_masked = cv2.bitwise_and(foreground_resized, foreground_resized, mask=mask_resized)

# Combine the results
result = cv2.add(background_masked, foreground_masked)

cv2.imshow('Composited Image', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

Real-Life Example: Document Scanner

Bitwise operations can be used in conjunction with other OpenCV functions to create a simple document scanner. This example demonstrates how to extract a document from a background using edge detection and bitwise operations.

    rect = np.zeros((4, 2), dtype="float32")
    s = pts.sum(axis=1)
    rect[0] = pts[np.argmin(s)]
    rect[2] = pts[np.argmax(s)]
    diff = np.diff(pts, axis=1)
    rect[1] = pts[np.argmin(diff)]
    rect[3] = pts[np.argmax(diff)]
    return rect

# Load image and preprocess
image = cv2.imread('document.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
edged = cv2.Canny(blurred, 75, 200)

# Find contours and identify the document
contours, _ = cv2.findContours(edged, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
doc_contour = max(contours, key=cv2.contourArea)

# Get corner points and transform perspective
peri = cv2.arcLength(doc_contour, True)
approx = cv2.approxPolyDP(doc_contour, 0.02 * peri, True)
doc_cnr = order_points(approx.reshape(4, 2))

(tl, tr, br, bl) = doc_cnr
width = max(int(np.linalg.norm(br - bl)), int(np.linalg.norm(tr - tl)))
height = max(int(np.linalg.norm(tr - br)), int(np.linalg.norm(tl - bl)))

dst = np.array([[0, 0], [width - 1, 0], [width - 1, height - 1], [0, height - 1]], dtype="float32")
M = cv2.getPerspectiveTransform(doc_cnr, dst)
warped = cv2.warpPerspective(image, M, (width, height))

# Create a mask for the document
mask = np.zeros(image.shape[:2], dtype=np.uint8)
cv2.drawContours(mask, [approx], -1, (255), -1)

# Extract the document using bitwise AND
result = cv2.bitwise_and(image, image, mask=mask)

cv2.imshow('Original Image', image)
cv2.imshow('Extracted Document', result)
cv2.imshow('Warped Document', warped)
cv2.waitKey(0)
cv2.destroyAllWindows()

Additional Resources

For more advanced topics and in-depth understanding of bitwise operations in image processing, consider exploring the following resources:

  1. OpenCV Documentation: https://docs.opencv.org/
  2. "Digital Image Processing" by Rafael C. Gonzalez and Richard E. Woods
  3. ArXiv paper: "A Survey of Deep Learning Techniques for Image Processing" (https://arxiv.org/abs/2009.08925)
  4. ArXiv paper: "Image Processing Using Bitwise Operations: A Comprehensive Review" (https://arxiv.org/abs/2103.05985)

These resources provide a solid foundation for further exploration of bitwise operations and their applications in computer vision and image processing.

More in Python for ML and AI

  1. Mastering isinstance() and issubclass() in Python9 min

    The isinstance() function is a crucial Python built-in that checks if an object belongs to a specified class or type. It returns True if the object is an...

  2. Masked Attention for Graphs (MAG) in Python11 min

    Masked Attention for Graphs (MAG) is a technique used in graph neural networks to improve the efficiency and effectiveness of attention mechanisms when...

  3. Mastering Python Function Parameter Order7 min

    Parameter order in Python functions follows strict rules that affect how arguments are processed and matched during function calls. Understanding these rules...

  4. Marketing Analytics Fundamentals with Python4 min

    This revised slide deck covers a wide range of marketing analytics topics, including data collection, preprocessing, exploratory data analysis, customer...

  5. Mastering Python Loops Efficient Repetition7 min

    The fundamental building blocks of iteration in Python are loops, which enable code execution multiple times with different data. Loops provide an efficient...

  6. Manipulating Bits with Python's Bitwise Operators9 min

    Binary numbers form the foundation of all computer operations, representing data as sequences of 0s and 1s. In Python, integers are stored internally as...