DepthAI Tutorials
DepthAI API References

ON THIS PAGE

  • RGB Rotate Warp
  • Setup
  • Demo
  • Source code
  • Pipeline

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 script
Command Line
1git clone https://github.com/luxonis/depthai-python.git
2cd depthai-python/examples
3python3 install_requirements.py
For additional information, please follow the installation guide.

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

Python
GitHub
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.