Skip to content

Instantly share code, notes, and snippets.

@cheadrian
Created December 10, 2023 22:10
Show Gist options
  • Save cheadrian/365ca2ae4997cec28790ab88a042b9d5 to your computer and use it in GitHub Desktop.
Save cheadrian/365ca2ae4997cec28790ab88a042b9d5 to your computer and use it in GitHub Desktop.
Adaptive Threshold, Sobel, Morph Close comparison with Matplotlib sliders
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
def sobel_edge_detector(img, threshold=50):
grad_x = cv.Sobel(img, cv.CV_64F, 1, 0)
grad_y = cv.Sobel(img, cv.CV_64F, 0, 1)
grad = np.sqrt(grad_x**2 + grad_y**2)
grad_norm = (grad * 255 / grad.max()).astype(np.uint8)
_, binary_edge = cv.threshold(grad_norm, threshold, 255, cv.THRESH_BINARY)
return binary_edge
def update(val):
# Get current slider values
block_size = int(block_size_slider.val)
C = int(C_slider.val)
blur_size = int(blur_size_slider.val)
closing_size = int(closing_size_slider.val)
sobel_threshold = int(sobel_threshold_slider.val)
# Apply Sobel edge detection
sobel_edges = sobel_edge_detector(gray, sobel_threshold)
# Apply blur
blurred_image = cv.GaussianBlur(gray, (blur_size, blur_size), 0)
# Apply adaptive thresholding
adaptive_threshold = cv.adaptiveThreshold(
blurred_image, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY_INV, block_size, C
)
# Apply morphological closing to close contours
kernel = np.ones((closing_size, closing_size), np.uint8)
closed_contours = cv.morphologyEx(adaptive_threshold, cv.MORPH_CLOSE, kernel)
# Update the displayed images
ax2.imshow(closed_contours, cmap='gray')
ax2.set_title('Adaptive Thresholded with Blur and Closed Contours')
ax3.imshow(sobel_edges, cmap='gray')
ax3.set_title('Sobel Edge Detection')
fig.canvas.draw_idle()
# Load the image
img = cv.imread('capture.png')
assert img is not None, "file could not be read, check with os.path.exists()"
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# Create figure and axes
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(18, 5))
fig.subplots_adjust(left=0.1, right=0.9, bottom=0.45)
# Display the original image
ax1.imshow(gray, cmap='gray')
ax1.set_title('Original Image')
# Initial values for adaptive threshold parameters
initial_block_size = 3
initial_C = 3
initial_blur_size = 3
initial_closing_size = 3
initial_sobel_threshold = 50
# Create sliders
axcolor = 'lightgoldenrodyellow'
ax_block_size = plt.axes([0.1, 0.35, 0.65, 0.03], facecolor=axcolor)
ax_C = plt.axes([0.1, 0.3, 0.65, 0.03], facecolor=axcolor)
ax_blur_size = plt.axes([0.1, 0.25, 0.65, 0.03], facecolor=axcolor)
ax_closing_size = plt.axes([0.1, 0.2, 0.65, 0.03], facecolor=axcolor)
ax_sobel_threshold = plt.axes([0.1, 0.15, 0.65, 0.03], facecolor=axcolor)
block_size_slider = Slider(ax_block_size, 'Block Size', 3, 31, valinit=initial_block_size, valstep=2)
C_slider = Slider(ax_C, 'C', -10, 20, valinit=initial_C, valstep=1)
blur_size_slider = Slider(ax_blur_size, 'Blur Size', 1, 21, valinit=initial_blur_size, valstep=2)
closing_size_slider = Slider(ax_closing_size, 'Closing Size', 1, 21, valinit=initial_closing_size, valstep=2)
sobel_threshold_slider = Slider(ax_sobel_threshold, 'Sobel Threshold', 0, 255, valinit=initial_sobel_threshold, valstep=1)
# Register the update function with the sliders
block_size_slider.on_changed(update)
C_slider.on_changed(update)
blur_size_slider.on_changed(update)
closing_size_slider.on_changed(update)
sobel_threshold_slider.on_changed(update)
# Initial blur and adaptive thresholding
blurred_image = cv.GaussianBlur(gray, (initial_blur_size, initial_blur_size), 0)
adaptive_threshold = cv.adaptiveThreshold(
blurred_image, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY_INV, initial_block_size, initial_C
)
# Initial morphological closing to close contours
kernel = np.ones((initial_closing_size, initial_closing_size), np.uint8)
closed_contours = cv.morphologyEx(adaptive_threshold, cv.MORPH_CLOSE, kernel)
# Initial Sobel edge detection
sobel_edges = sobel_edge_detector(gray, initial_sobel_threshold)
# Display the adaptive thresholded image with closed contours
ax2.imshow(closed_contours, cmap='gray')
ax2.set_title('Adaptive Thresholded with Blur and Closed Contours')
# Display the Sobel edge detection
ax3.imshow(sobel_edges, cmap='gray')
ax3.set_title('Sobel Edge Detection')
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment