ON THIS PAGE

  • RGB Rotate Warp
  • 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.This example requires the DepthAI v3 API, see installation instructions.

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.