This tutorial will be a basic introduction to OpenCV and some basic Instagram filters
OpenCV is a library primarily built for computer vision. You do not need to be a pro in image processing to build a few simple image filters like Instagram’s sepia effect, Emboss effect, etc. We will be going over the following.
- How is an Image stored?
- Convolution and how Filters work
- Reading and Displaying Images
- Reading VideoCaptures and using your WebCam
- Some Filters and Image manipulation
How is an Image Stored?
Each image is made of pixels. The number of pixels in an image is determined by the width and height of the image. The above image is 3776 x 2832, and therefore it has 3776 x 2832 pixels in total. For black and white images, the image will have only one channel, but for a colored image, like the one above, there will be three channels, namely Red, Blue, and Green.
OpenCV stores the pixels in BGR Format.
All the channels will merge to form the final image. Therefore to answer the question, how is the image stored? It is stored in the form of a 3D array with shape (2832, 3776, 3). A black image will have a 3D array with all 0, while a white image will have a 3D array with all 256.
Convolution and How filters work?
Convolution is essentially breaking the image matrix into small parts and laying the filter matrix on top of it. We then process it and calculate the output. Some Filter matrices are listed below. The values for these matrices take years of research. Instagram filters are basically combinations of such low-level filters, such as blurs, contrast changes, color changes, etc.
I have linked a video by Computerphile below. It goes more in-depth about Convolution and examples of how filters work.
Install OpenCV
pip install opencv
To import the library, type.
import cv2
All the functions we discuss will be part of the cv2 package.
Reading and Displaying Images
img = cv2.imread('mainImage.jpg')
imread() takes in the path to the image as the parameter and returns the pixel values
cv2.imshow('Image Display' , img) cv2.waitKey(5000)
imshow() displays the image in a new window. The first parameter is the name of the window and the second parameter is the image object containing the pixel values. By default, the window closes right after it pops up, and therefore we can not see it. To solve the problem, we manually add a wait time. waitKey() takes in the number of milliseconds to wait before automatically closing the window. If you pass a value of 0, the window will be displayed for infinity milliseconds, i.e., forever until you close it manually.
Reading VideoCaptures and using your WebCam
cap = cv2.VideoCapture("testvideo.mp4")
We use VideoCapture() to read videos and use the webcam. It is pretty similar to imread(). It takes in a path to the video and reads it. To use your webcam, the parameter will be needed to be set to 0. This gives it access to your default webcam.
webCam = cv2.VideoCapture(0)
You can also set the width and height of the window using your webcam. You will need to know the parameter id to set the value. We will use the set() function.
webCam.set(3 ,500) # id 3 is width webCam.set(4,500) # id 4 is height webCam.set(10, 100) #id 10 is brightness
A video is basically a collection of images in a sequence; therefore, we will need a while loop and imread() function to display the video. The same method can be used to display the webcam as well.
while True: try: success , img = cap.read() cv2.imshow("Video", img) if cv2.waitKey(10) == ord('q'): break except: print('Video End') break
The value passed to waitkey() dictates the speed of your video. The higher the number, the slower the speed. If you put 0, which translates to an infinite wait time, you will only be able to see the first frame. The if statement essentially checks if the user presses the ‘q’ key. If the ‘q’ key is pressed, the window closes, and then we exit the while loop.
Common Filters
Original Image
import cv2 img = cv2.imread('ogImage.jpg') print(img.shape) cv2.imshow('Original Picture' , img) cv2.waitKey(0)
The shape of the image is
(427, 640, 3)
The pixels are store in BGR format.
GrayScale Image
img_gray = cv2.cvtColor(img , cv2.COLOR_BGR2GRAY) cv2.imshow('GrayScale' , img_gray)
Blur Image
img_blur = cv2.GaussianBlur(img , (15,15) , 0) cv2.imshow('Blur Image', img_blur)
The greater the Kernel Size, the more blurred the picture will be
img_blur = cv2.GaussianBlur(img , (25,25) , 0) cv2.imshow('Blur Image', img_blur)
Brightness
img_bright = cv2.convertScaleAbs(img, beta=100) cv2.imshow('Less Bright Image', img_bright)
As the value of beta increases, the picture becomes brighter. To decrease brightness, use negative values.
img_bright = cv2.convertScaleAbs(img, beta=-50) cv2.imshow('Less Bright Image', img_bright)
Edge Detection
img_canny = cv2.Canny(img , 100 ,100) cv2.imshow('Edge Detection Image', img_canny)
Emboss Effect
kernel = np.array([[0, -1, -1], [1, 0, -1], [1, 1, 0]]) img_sharpen = cv2.filter2D(img, -1, kernel) cv2.imshow('Embossed Image', img_sharpen)
Image Sharpening
kernel = np.array([[-1, -1, -1], [-1, 9, -1], [-1, -1, -1]]) img_sharpen = cv2.filter2D(img, -1, kernel) cv2.imshow('Sharpened Image', img_sharpen)
Sepia Effect
kernel = np.array([[0.272, 0.534, 0.131], [0.349, 0.686, 0.168], [0.393, 0.769, 0.189]]) img_sepia = cv2.filter2D(img, -1, kernel) cv2.imshow('Sharpened Image', img_sepia)
Image Manipulation
Image Resize
img_resize = cv2.resize(img,(200,200)) cv2.imshow('Resized Image', img_resize) cv2.waitKey(0)
Image Crop
img_cropped = img[0:256 , 0:256] cv2.imshow('Cropped Image', img_cropped)
Since the image is stored as a matrix, we can just slice it to crop the image.
Resources
Let me know if you find any more cool filters or functions. I’d love to try them out! 😃