RGB Rotate Warp
This example shows usage of ImageManip to crop a rotated rectangle area on a frame, or perform various image transforms: rotate, mirror, flip, perspective transform.Setup
Please run the install script to download all required dependencies. Please note that this script must be ran from git context, so you have to download the depthai-python repository first and then run the scriptCommand Line
1git clone https://github.com/luxonis/depthai-python.git
2cd depthai-python/examples
3python3 install_requirements.py
Demo
Command Line
1Controls:
2z -rotated rectangle crop, decrease rate
3x -rotated rectangle crop, increase rate
4c -warp 4-point transform, cycle through modes
5v -resize cropped region, or disable resize
6h -print controls (help)
Source code
Python
C++
Python
PythonGitHub
1#!/usr/bin/env python3
2
3"""
4This example shows usage of ImageManip to crop a rotated rectangle area on a frame,
5or perform various image transforms: rotate, mirror, flip, perspective transform.
6"""
7
8import depthai as dai
9import cv2
10import numpy as np
11
12keyRotateDecr = 'z'
13keyRotateIncr = 'x'
14keyResizeInc = 'v'
15keyWarpTestCycle = 'c'
16
17def printControls():
18 print("=== Controls:")
19 print(keyRotateDecr, "-rotated rectangle crop, decrease rate")
20 print(keyRotateIncr, "-rotated rectangle crop, increase rate")
21 print(keyWarpTestCycle, "-warp 4-point transform, cycle through modes")
22 print(keyResizeInc, "-resize cropped region, or disable resize")
23 print("h -print controls (help)")
24
25rotateRateMax = 5.0
26rotateRateInc = 0.1
27
28resizeMaxW = 800
29resizeMaxH = 600
30resizeFactorMax = 5
31
32'''
33The crop points are specified in clockwise order,
34with first point mapped to output top-left, as:
35 P0 -> P1
36 ^ v
37 P3 <- P2
38'''
39P0 = [0, 0] # top-left
40P1 = [1, 0] # top-right
41P2 = [1, 1] # bottom-right
42P3 = [0, 1] # bottom-left
43
44warpList = [
45 # points order, normalized cordinates, description
46 # [[[0, 0], [1, 0], [1, 1], [0, 1]], True, "passthrough"],
47 # [[[0, 0], [639, 0], [639, 479], [0, 479]], False, "passthrough (pixels)"],
48 [[P0, P1, P2, P3], True, "1. passthrough"],
49 [[P3, P0, P1, P2], True, "2. rotate 90"],
50 [[P2, P3, P0, P1], True, "3. rotate 180"],
51 [[P1, P2, P3, P0], True, "4. rotate 270"],
52 [[P1, P0, P3, P2], True, "5. horizontal mirror"],
53 [[P3, P2, P1, P0], True, "6. vertical flip"],
54 [[[-0.1, -0.1], [1.1, -0.1], [1.1, 1.1], [-0.1, 1.1]], True, "7. add black borders"],
55 [[[-0.3, 0], [1, 0], [1.3, 1], [0, 1]], True, "8. parallelogram transform"],
56 [[[-0.2, 0], [1.8, 0], [1, 1], [0, 1]], True, "9. trapezoid transform"],
57]
58
59# Create pipeline
60pipeline = dai.Pipeline()
61
62# Define sources and outputs
63camRgb = pipeline.create(dai.node.ColorCamera)
64manip = pipeline.create(dai.node.ImageManip)
65
66camOut = pipeline.create(dai.node.XLinkOut)
67manipOut = pipeline.create(dai.node.XLinkOut)
68manipCfg = pipeline.create(dai.node.XLinkIn)
69
70camOut.setStreamName("preview")
71manipOut.setStreamName("manip")
72manipCfg.setStreamName("manipCfg")
73
74# Properties
75camRgb.setPreviewSize(640, 480)
76camRgb.setResolution(dai.ColorCameraProperties.SensorResolution.THE_1080_P)
77camRgb.setInterleaved(False)
78camRgb.setColorOrder(dai.ColorCameraProperties.ColorOrder.BGR)
79manip.setMaxOutputFrameSize(2000 * 1500 * 3)
80
81# Linking
82camRgb.preview.link(camOut.input)
83camRgb.preview.link(manip.inputImage)
84manip.out.link(manipOut.input)
85manipCfg.out.link(manip.inputConfig)
86
87# Connect to device and start pipeline
88with dai.Device(pipeline) as device:
89
90 # Create input & output queues
91 qPreview = device.getOutputQueue(name="preview", maxSize=4)
92 qManip = device.getOutputQueue(name="manip", maxSize=4)
93 qManipCfg = device.getInputQueue(name="manipCfg")
94
95 key = -1
96 angleDeg = 0
97 rotateRate = 1.0
98 resizeFactor = 0
99 resizeX = 0
100 resizeY = 0
101 testFourPt = False
102 warpIdx = -1
103
104 printControls()
105
106 while key != ord('q'):
107 if key > 0:
108 print("Pressed: ", key)
109 if key == ord(keyRotateDecr) or key == ord(keyRotateIncr):
110 if key == ord(keyRotateDecr):
111 if rotateRate > -rotateRateMax:
112 rotateRate -= rotateRateInc
113 if key == ord(keyRotateIncr):
114 if rotateRate < rotateRateMax:
115 rotateRate += rotateRateInc
116 testFourPt = False
117 print("Crop rotated rectangle, rate per frame: {:.1f} degrees".format(rotateRate))
118 elif key == ord(keyResizeInc):
119 resizeFactor += 1
120 if resizeFactor > resizeFactorMax:
121 resizeFactor = 0
122 print("Crop region not resized")
123 else:
124 resizeX = resizeMaxW // resizeFactor
125 resizeY = resizeMaxH // resizeFactor
126 print("Crop region resized to: ", resizeX, 'x', resizeY)
127 elif key == ord(keyWarpTestCycle):
128 # Disable resizing initially
129 resizeFactor = 0
130 warpIdx = (warpIdx + 1) % len(warpList)
131 testFourPt = True
132 testDescription = warpList[warpIdx][2]
133 print("Warp 4-point transform: ", testDescription)
134 elif key == ord('h'):
135 printControls()
136
137 # Send an updated config with continuous rotate, or after a key press
138 if key >= 0 or (not testFourPt and abs(rotateRate) > 0.0001):
139 cfg = dai.ImageManipConfig()
140 if testFourPt:
141 test = warpList[warpIdx]
142 points, normalized = test[0], test[1]
143 point2fList = []
144 for p in points:
145 pt = dai.Point2f()
146 pt.x, pt.y = p[0], p[1]
147 point2fList.append(pt)
148 cfg.setWarpTransformFourPoints(point2fList, normalized)
149 else:
150 angleDeg += rotateRate
151 rotatedRect = ((320, 240), (400, 400), angleDeg)
152 rr = dai.RotatedRect()
153 rr.center.x, rr.center.y = rotatedRect[0]
154 rr.size.width, rr.size.height = rotatedRect[1]
155 rr.angle = rotatedRect[2]
156 cfg.setCropRotatedRect(rr, False)
157 if resizeFactor > 0:
158 cfg.setResize(resizeX, resizeY)
159 # cfg.setWarpBorderFillColor(255, 0, 0)
160 # cfg.setWarpBorderReplicatePixels()
161 qManipCfg.send(cfg)
162
163 for q in [qPreview, qManip]:
164 pkt = q.get()
165 name = q.getName()
166 shape = (3, pkt.getHeight(), pkt.getWidth())
167 frame = pkt.getCvFrame()
168 if name == "preview" and not testFourPt:
169 # Draw RotatedRect cropped area on input frame
170 points = np.int0(cv2.boxPoints(rotatedRect))
171 cv2.drawContours(frame, [points], 0, (255, 0, 0), 1)
172 # Mark top-left corner
173 cv2.circle(frame, tuple(points[1]), 10, (255, 0, 0), 2)
174 cv2.imshow(name, frame)
175 key = cv2.waitKey(1)
Pipeline
Need assistance?
Head over to Discussion Forum for technical support or any other questions you might have.