<jupyter_start><jupyter_text>Creating a Filter, Edge Detection  Import resources and display image<jupyter_code>import matplotlib.pyplot as plt
import matplotlib.image as mpimg

import cv2
import numpy as np

%matplotlib inline

# Read in the image
image = mpimg.imread('images/curved_lane.jpg')

plt.imshow(image)<jupyter_output><empty_output><jupyter_text>Convert the image to grayscale<jupyter_code># Convert to grayscale for filtering
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

plt.imshow(gray, cmap='gray')<jupyter_output><empty_output><jupyter_text>TODO: Create a custom kernelBelow, you've been given one common type of edge detection filter: a Sobel operator.The Sobel filter is very commonly used in edge detection and in finding patterns in intensity in an image. Applying a Sobel filter to an image is a way of **taking (an approximation) of the derivative of the image** in the x or y direction, separately. The operators look as follows.**It's up to you to create a Sobel x operator and apply it to the given image.**For a challenge, see if you can put the image through a series of filters: first one that blurs the image (takes an average of pixels), and then one that detects the edges.<jupyter_code># Create a custom kernel

# 3x3 array for edge detection
cfilter = np.array([[ -1, -2, -1], 
                   [ 0, 0, 0], 
                   [ 1, 2, 1]])

# Filter the image using filter2D, which has inputs: (grayscale image, bit-depth, kernel)  
filtered_image = cv2.filter2D(gray, -1, cfilter)

plt.imshow(filtered_image, cmap='gray')<jupyter_output><empty_output><jupyter_text>Seems like the horizontal filter does well at detecting the edges of the road...  Test out other filters!You're encouraged to create other kinds of filters and apply them to see what happens! As an **optional exercise**, try the following:* Create a filter with decimal value weights.* Create a 5x5 filter* Apply your filters to the other images in the `images` directory.<jupyter_code># 3x3 array for edge detection
cfilter = np.array([[ -1, 0, 1], 
                   [ -2, 0, 2], 
                   [ -1, 0, 1]])

# Filter the image using filter2D, which has inputs: (grayscale image, bit-depth, kernel)  
filtered_image = cv2.filter2D(gray, -1, cfilter)

plt.imshow(filtered_image, cmap='gray')<jupyter_output><empty_output><jupyter_text>Whereas the vertical filter enhances the edges of the horizontal hill range in the background (because the hill is composed of vertical piles of pixels... i.e. TREES? Quite cool).<jupyter_code>cfilter = np.array([[ 0, -1, 0], 
                   [ -1, 4, -1], 
                   [ 0, -1, 0]])

# Filter the image using filter2D, which has inputs: (grayscale image, bit-depth, kernel)  
filtered_image = cv2.filter2D(gray, -1, cfilter)

plt.imshow(filtered_image, cmap='gray')<jupyter_output><empty_output><jupyter_text>This filter doesn't do much...<jupyter_code>cfilter = np.array([[ 1, -1, 0], 
                   [ -1, 2, -1], 
                   [ 0, -1, 1]])

# Filter the image using filter2D, which has inputs: (grayscale image, bit-depth, kernel)  
filtered_image = cv2.filter2D(gray, -1, cfilter)

plt.imshow(filtered_image, cmap='gray')
Neither does this one...
cfilter = np.array([[ 0, -1, 1], 
                   [ -1, 2, -1], 
                   [ 1, -1, 0]])

# Filter the image using filter2D, which has inputs: (grayscale image, bit-depth, kernel)  
filtered_image = cv2.filter2D(gray, -1, cfilter)

plt.imshow(filtered_image, cmap='gray')<jupyter_output><empty_output><jupyter_text>...or this one.<jupyter_code>cfilter = np.array([[ 0, 1, 1, 1, 0], 
                    [ 0, 0, 0, 0, 0], 
                    [ 0, 0, 0, 0, 0],
                    [ 0, 0, 0, 0, 0],
                    [ 0, -1, -1, -1, 0]])

# Filter the image using filter2D, which has inputs: (grayscale image, bit-depth, kernel)  
filtered_image = cv2.filter2D(gray, -1, cfilter)

plt.imshow(filtered_image, cmap='gray')<jupyter_output><empty_output><jupyter_text>Seems like a larger filter enhances the edges more...<jupyter_code>cfilter = np.array([[ 0, 1, 1, 1, 0], 
                    [ 0, 1, 1, 1, 0], 
                    [ 0, 0, 0, 0, 0],
                    [ 0, -1, -1, -1, 0],
                    [ 0, -1, -1, -1, 0]])

# Filter the image using filter2D, which has inputs: (grayscale image, bit-depth, kernel)  
filtered_image = cv2.filter2D(gray, -1, cfilter)

plt.imshow(filtered_image, cmap='gray')<jupyter_output><empty_output><jupyter_text>...quite independent of the number of positive and negative values...<jupyter_code>cfilter = np.array([[ 0, 2, 2, 2, 0], 
                    [ 0, 2, 2, 2, 0], 
                    [ 0, 0, 0, 0, 0],
                    [ 0, -2, -2, -2, 0],
                    [ 0, -2, -2, -2, 0]])

# Filter the image using filter2D, which has inputs: (grayscale image, bit-depth, kernel)  
filtered_image = cv2.filter2D(gray, -1, cfilter)

plt.imshow(filtered_image, cmap='gray')<jupyter_output><empty_output><jupyter_text>...as long as the filter has the right shape.<jupyter_code>cfilter = np.array([[ 0, 4, 4, 4, 0], 
                    [ 0, 4, 4, 4, 0], 
                    [ 0, 0, 0, 0, 0],
                    [ 0, -4, -4, -4, 0],
                    [ 0, -4, -4, -4, 0]])

# Filter the image using filter2D, which has inputs: (grayscale image, bit-depth, kernel)  
filtered_image = cv2.filter2D(gray, -1, cfilter)

plt.imshow(filtered_image, cmap='gray')<jupyter_output><empty_output><jupyter_text>But make the values in the filter too big...<jupyter_code>cfilter = np.array([[ 0, 10, 10, 10, 0], 
                    [ 0, 10, 10, 10, 0], 
                    [ 0, 0, 0, 0, 0],
                    [ 0, -10, -10, -10, 0],
                    [ 0, -10, -10, -10, 0]])

# Filter the image using filter2D, which has inputs: (grayscale image, bit-depth, kernel)  
filtered_image = cv2.filter2D(gray, -1, cfilter)

plt.imshow(filtered_image, cmap='gray')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1291296327352004, 'fraction_numerical': 0.038906590642294146, 'mean_word_length': 2.8777633289986997, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 5, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '11', 'dir': 'jupyter-structured-clean-dedup', 'id': '139556', 'license': 'MIT', 'n_tokens_mistral': 2238, 'n_tokens_neox': 1991, 'n_words': 669, 'path': 'convolutional-neural-networks/conv-visualization/custom_filters.ipynb', 'repo_name': 'SirObi/pytorch-projects', 'size': '5963'}