--- tags: OpenCV --- # OpenCV with Python -- 3 [Back to book mode](https://hackmd.io/@Justin123/opencv) ## Introduction In today's tutorial, we're going to talk about how to crop the image. Also, add additional infomation on the images such as lines, retangle and text. Furthermore, we 'are going to know how to change the perspective of the image. ## Resize and crop We have already mentioned how to resize the image. However, in some special event, we want to random crop our image or crop the image at the center to get the specific information. For example, when we train the classification model and want to improve the performance, we may try to do the random crop to get different kinds of images. (In fact, most of the deep learning library have built-in function to finish the job.) Essentially put, image is a matrix will value in it. Therefore, if we want to crop the image, we can just focus on one part of the matrix and only get those values. The only thing should be noticed is the matrix was start from top-left corner. <center><img src=https://i.imgur.com/hYdL50V.jpg width=450/></center> * **Function in OpenCV** ```python= import cv2 img = cv2.imread("resources/food.jpg") ''' # Crop the image target region: (height, width) height pixel: 500~900 width pixel: 300~1000 ''' img_cropped = img[500:900, 300:1000] # Show the image cv2.imshow("Image", img) cv2.imshow("Cropped image", img_cropped) cv2.waitKey(0) cv2.destroyAllWindows() cv2.waitKey(1) ``` <center><img src=https://i.imgur.com/7nJCIm4.jpg width=450/></center> <center><b>Origin image</b></center></br> <center><img src=https://i.imgur.com/4XChJqz.jpg width=250/></center> <center><b>Cropped image</b></center> ## Draw on the image We're going to demonstrate how to use the function. * **Circle** * `cv2.circle(img, origin, radius, color, thickness)` * img: Image to draw * origin: Pixel to be the origin. * radius: Radius of the circle. * color: Color of the circle. ==(RGB)== * thickness: Thickness of the circle. To fill the circle put `cv2.FILLED`. </br> ```python # Example cv2.circle(img_cir, (250, 250), 100, (255, 0, 255), 3) cv2.circle(img_cir, (250, 250), 100, (255, 0, 255), cv2.FILLED) ``` * **Rectangle** * `cv2.rectangle(img, upper_left, lower_right, color, thickness)` * img: Image to add rectangle. * upper_left: Top-left corner of the rectangle. ==(Place of the matrix)== * lower_right: Down-right corner of the rectangle. ==(Place of the matrix)== * color: Color of rectangle. * thickness: Thickness of rectangle. To fill the circle put `cv2.FILLED`. </br> ```python # Example cv2.rectangle(img_rec, (0, 0), (250, 350), (0, 0, 255), 3) cv2.rectangle(img_rec, (250, 350), (250, 350), (255, 0, 0), cv2.FILLED) ``` * **Line** * `cv2.line(img, start_point, end_point, color, thickness)` * img: Image to add line. * start_point: Position to start line. ==(Place of the matrix)== * end_point: Position to end line. ==(Place of the matrix)== * color: Color of line. * thickness: Thickness of line. </br> ```python cv2.line(img_line, (0, 0), (img.shape[1], img.shape[0]), (0, 255, 0), 3) ``` * **Text** * `cv2.putText(img, text, start_place, font type, scale, color, thickness)` * text: Text to be put on. * start_point: buttom-left corner of the text. ==(Place of the matrix)== * font type: The type of the text. * scale: Scale of the text. </br> ```python cv2.putText(img_text, "OpenCV", (300, 100), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 255), 3) ``` **Demostration** ```python= import cv2 import numpy as np ''' # Create a black image 0: black 255: white ''' img_black = np.zeros((512, 512), np.uint8) # Create color image, need 3 channels img_blue = np.zeros((512, 512, 3), np.uint8) img_blue[:] = [255, 0, 0] ''' Try out img_blue[200:300, 300, 400] = [255, 0, 0] ''' # Add green line img_line = np.zeros((512, 512, 3), np.uint8) cv2.line(img_line, (0, 0), (img.shape[1], img.shape[0]), (0, 255, 0), 3) ## Add rectangle img_rec = np.zeros((512, 512, 3), np.uint8) cv2.rectangle(img_rec, (0, 0), (250, 350), (0, 0, 255), 3) cv2.rectangle(img_rec, (250, 350), (img.shape[1], img.shape[0]), (255, 0, 0), cv2.FILLED) ## Add Circle img_cir = np.zeros((512, 512, 3), np.uint8) cv2.circle(img_cir, (250, 250), 100, (255, 0, 255), cv2.FILLED) ## Add Text img_text = np.zeros((512, 512, 3), np.uint8) cv2.putText(img_text, "OpenCV", (300, 100), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 255), 3) # Show the result cv2.imshow("Black image", img_black) cv2.imshow("Blue image", img_blue) cv2.imshow("Line", img_line) cv2.imshow("Rectangle", img_rec) cv2.imshow("Circle", img_cir) cv2.imshow("Text", img_text) cv2.waitKey(0) cv2.destroyAllWindows() cv2.waitKey(1) ``` ## Perspective To get the specific part of the image, we have to change the perspective of the image. For example, we have lots of pockers. <center><img src=https://i.imgur.com/KShrc4c.jpg width=300/></center> </br> We only want to get the **Ace** in the image. <center><img src=https://i.imgur.com/nH4WtdI.jpg width=200/></center> </br> Let's see how we achieve the result. In order to change the perspective, we should first know all four vertexs of the target. After that, we have to determine the new size of the image. Then we can do the transform. ![](https://i.imgur.com/68aExgZ.jpg) You can use different application such as Photoshop or just the image viewer in your computer to find out the vertex. The order of `pst1`(in below code session) doesn't matter. However, you should be aware the order of `pst2` should have the right transformation w.r.t. `pst1`. ```python= import cv2 import numpy as np img = cv2.imread("resources/pocker.jpg") cv2.imshow("Image", img) # New size of the output width, height = 250, 350 ''' pst1: old position pst2: new position transform pst1 -> pst2 ''' pts1 = np.float32([[239, 103], [356, 146], [179, 277], [296, 320]]) pts2 = np.float32([[0, 0], [width, 0], [0, height], [width, height]]) # Transformation matrix matrix = cv2.getPerspectiveTransform(pts1, pts2) # Get the new image img_output = cv2.warpPerspective(img, matrix, (width, height)) cv2.imshow("New image", img_output) cv2.waitKey(0) cv2.destroyAllWindows() cv2.waitKey(1) ``` Try to break the correct transformation or change the order to see the result by yourself! </br> For instance: ```python # Break the correct transformation pts1 = np.float32([[356, 146], [239, 103], [179, 277], [296, 320]]) pts2 = np.float32([[0, 0], [width, 0], [0, height], [width, height]]) #-------------------# # Change the order but still with right transformation pts1 = np.float32([[356, 146], [239, 103], [179, 277], [296, 320]]) pts2 = np.float32([[width, 0], [0, 0], [0, height], [width, height]]) ``` ## Join the image To show different kinds of images in one result or feel tedious to type `cv2.imshow(...)` we can stack the images together. * `np.hstack()` We use numpy function to stack the image. You can make a list of images to be the input. </br></br> ```python= import cv2 import numpy as np img = cv2.imread("resources/food.jpg") # horizotal stack img_hor = np.hstack((img, img)) # Show the result cv2.imshow("Horizontal image", img_hor) cv2.waitKey(0) cv2.destroyAllWindows() cv2.waitKey(1) ``` <center><img src=https://i.imgur.com/Kw85NL3.jpg width=500/></center> * `np.vstack()` Same as `np.hstack()`, but with the vertical result. ```python= import cv2 import numpy as np img = cv2.imread("resources/food.jpg") # Vertival stack img_ver = np.vstack((img, img)) # Show the result cv2.imshow("Vertical image", img_ver) cv2.waitKey(0) cv2.destroyAllWindows() cv2.waitKey(1) ``` <center><img src=https://i.imgur.com/294x66t.jpg height=450/></center> * **Self-define function** To first scale the image and stack the images with multilayers, we can write our own function. ==The code below is came from [MURTAZA'S WORKSHOP](https://www.murtazahassan.com/learn-opencv-in-3-hours-chapter-6/).== ```python= ''' The code below came from MURTAZA'S WORKSHOP ''' def stackImages(scale, imgArray): ''' scale: New scale of the image imgArray: Images to stack. ''' rows = len(imgArray) cols = len(imgArray[0]) # Check whether we have multilayers rowsAvailable = isinstance(imgArray[0], list) width = imgArray[0][0].shape[1] height = imgArray[0][0].shape[0] if rowsAvailable: for x in range (0, rows): for y in range(0, cols): if imgArray[x][y].shape[:2] == imgArray[0][0].shape[:2]: imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale) else: imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale) if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor(imgArray[x][y], cv2.COLOR_GRAY2BGR) imageBlank = np.zeros((height, width, 3), np.uint8) hor = [imageBlank] * rows # First put each horizontal image to its horizontal place for x in range(0, rows): hor[x] = np.hstack(imgArray[x]) # Stack each array to the vertical format ver = np.vstack(hor) else: for x in range(0, rows): if imgArray[x].shape[:2] == imgArray[0].shape[:2]: imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale) else: imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale) if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR) hor = np.hstack(imgArray) ver = hor return ver ``` ```python= import cv2 import numpy as np img = cv2.imread('resources/beauty.jpg') img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # Stack image img_stack = stackImages(0.5, [[img, img_gray, img],[img, img, img]]) # Show the image cv2.imshow("ImageStack",img_stack) cv2.waitKey(0) cv2.destroyAllWindows() cv2.waitKey(1) ``` <center><img src=https://i.imgur.com/OG3q7DP.jpg width=500/></center> ## Reference 1. [MURTAZA'S WORKSHOP](https://www.murtazahassan.com/learn-opencv-in-3-hours-chapter-6/) 2. [LEARN OPENCV in 3 HOURS with Python (2020)](https://youtu.be/WQeoO7MI0Bs)