import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
import numpy as np
import cv2
import math
%matplotlib inline
image = cv2.imread('stopsign.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image = cv2.resize(image, (300, 200))
image = image[0:150, 100:250, :] # scope to stop sign
original = np.copy(image)
plt.imshow(image)
<matplotlib.image.AxesImage at 0x1137f6b10>
# create a binary image to detect contours in (here only red)
lower_red = np.array([100,0,0])
upper_red = np.array([255,60,60])
# Mask the image
image = np.copy(original)
mask = cv2.inRange(image, lower_red, upper_red)
image[mask > 0] = [255, 255, 255]
image[mask == 0] = [0, 0, 0]
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
_, binary = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY)
# Display it
plt.subplot(121)
plt.imshow(original)
plt.subplot(122)
plt.imshow(binary, cmap='gray')
<matplotlib.image.AxesImage at 0x116a55450>
# draw all the contours that were found
## finding multiple contours because the binary image has multiple edges
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # syntax for opencv 2.4
cols = 4
rows = math.ceil(len(contours) * 1.0 / cols)
plt.figure(figsize=(16, 16))
plt.subplot(rows, cols, 1)
for i in range(len(contours)):
plt.subplot(rows, cols, i+1)
image_contours = np.copy(original)
cv2.drawContours(image_contours, contours, i, (0, 255, 0), 2)
plt.imshow(image_contours)
plt.title("contour #{}".format(i))
plt.xticks([]), plt.yticks([])
contour #4 seems to be the main sign contour
Image taken from https://www.publicdomainpictures.net/en/view-image.php?image=174629&picture=hand-with-thumb-up-and-down under CC0 Public Domain
image = cv2.imread('thumbs.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image = cv2.resize(image, (600, 400))
original = np.copy(image)
plt.subplot(121)
plt.imshow(original)
plt.xticks([]), plt.yticks([]);
plt.subplot(122)
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
_, binary = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV)
plt.imshow(binary, cmap='gray')
plt.xticks([]), plt.yticks([]);
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print("Found {} contours".format(len(contours)))
Found 2 contours
plt.figure(figsize=(16, 16))
plt.subplot(1, 2, 1)
for i in range(len(contours)):
plt.subplot(1, 2, i+1)
image_contours = np.copy(original)
# draw the contour in green
cv2.drawContours(image_contours, contours, i, (0, 255, 0), 2)
# plot a fitted ellipse in cyan
ellipse = cv2.fitEllipse(contours[i])
cv2.ellipse(image_contours, ellipse, (0, 255, 255), 2)
[vx,vy,x,y] = cv2.fitLine(contours[i], cv2.cv.CV_DIST_L2, 0, 0.01, 0.01)
line_length = 300
# plot a fitted line in red
cv2.line(image_contours, (x - vx*line_length/2, y - vy*line_length/2), (x + vx*line_length/2, y + vy*line_length/2),(255,0,0),2)
plt.imshow(image_contours)
plt.title("contour #{} at angle {} deg".format(i, ellipse[1][1]))
plt.xticks([]), plt.yticks([])
image = cv2.imread('torturm.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image = cv2.resize(image, (400, 600))
original = np.copy(image)
# extract edges using canny edge detection
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
lower = 100
upper = 200
edges = cv2.Canny(gray, lower, upper)
plt.figure(figsize=(14, 9))
plt.imshow(edges, cmap='gray')
<matplotlib.image.AxesImage at 0x10a791fd0>
# find lines in hough space
rho = 1 # 1 pix
theta = np.pi/180 # 1 degree
threshold = 60
min_line_length = 50
max_line_gap = 10
lines = cv2.HoughLinesP(edges, rho, theta, threshold, np.array([]), min_line_length, max_line_gap)
image_lines = np.copy(original)
for l in lines:
for x1, y1, x2, y2 in l:
cv2.line(image_lines, (x1, y1), (x2, y2), (255, 0, 255), 2)
plt.figure(figsize=(15,9))
plt.imshow(image_lines)
<matplotlib.image.AxesImage at 0x117531390>
Looks like hough space doesn't work so well for houses :/
image = cv2.imread('torturm.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image = cv2.resize(image, (400, 600))
original = np.copy(image)
plt.imshow(original)
<matplotlib.image.AxesImage at 0x11e75b9d0>
# concatenate X and Y axis into one dimension and uint8 -> float32
pixels = np.float32(image.reshape((-1, 3)))
print("Converted dimension {} into {}".format(image.shape, pixels.shape))
Converted dimension (600, 400, 3) into (240000, 3)
# clustering
stop_criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0) # see https://docs.opencv.org/2.4/modules/core/doc/clustering.html?highlight=kmeans#cv2.kmeans
k = 3
restart_count = 5
_, labels, centers = cv2.kmeans(pixels, k, stop_criteria, restart_count, cv2.KMEANS_RANDOM_CENTERS)
# convert centers into uint points and labels back to image shape
centers = np.uint8(centers)
data = centers[labels.flatten()] # for each pixel pick the corresponding k-means center value
image_clustered = data.reshape((image.shape))
labels_clustered = labels.reshape(image.shape[0], image.shape[1])
plt.imshow(image_clustered)
<matplotlib.image.AxesImage at 0x11eb650d0>
# show image parts for the individual labels, top left showing the segment center
legend_length = 80
legend_border = 8
legend_border_color = [255, 0, 255]
cols = 4
rows = math.ceil(k * 1.0 / cols)
plt.figure(figsize=(16, 16))
plt.subplot(rows, cols, 1)
for i in range(k):
plt.subplot(rows, cols, i + 1)
image_masked = np.copy(original)
image_masked[labels_clustered != i] = [0, 255, 0]
image_masked[0:legend_length, 0:legend_length, :] = centers[i]
image_masked[0:legend_length + legend_border, legend_length:legend_length + legend_border, :] = legend_border_color
image_masked[legend_length:legend_length + legend_border, 0:legend_length + legend_border, :] = legend_border_color
plt.imshow(image_masked)
plt.title("cluster #{}".format(i))
plt.xticks([]), plt.yticks([])