DepthAI v2 has been superseded by DepthAI v3. You are viewing legacy documentation.
此页面由 AI 自动翻译。查看英文原版
DepthAI 教程
DepthAI API 参考

本页目录

  • 设置
  • 演示
  • 源代码

RGB 旋转变形

此示例展示了如何使用 ImageManip 裁剪旋转矩形区域的帧, 或执行各种图像变换:旋转、镜像、翻转、透视变换。

设置

请运行 安装脚本 以下载所有必需的依赖项。请注意,此脚本必须在 git 上下文中运行,因此您必须先下载 depthai-python 存储库,然后运行脚本
Command Line
1git clone https://github.com/luxonis/depthai-python.git
2cd depthai-python/examples
3python3 install_requirements.py
有关更多信息,请遵循 安装指南

演示

https://user-images.githubusercontent.com/18037362/152208899-461fa163-42ec-4922-84b5-5cd09332ea32.png
Command Line
1控件:
2z -旋转矩形裁剪,降低速率
3x -旋转矩形裁剪,提高速率
4c -4点变换变形,循环模式
5v -调整裁剪区域大小,或禁用调整大小
6h -打印控件 (帮助)

源代码

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)

C++

1#include <iostream>
2
3#include "depthai/depthai.hpp"
4#include "utility.hpp"
5
6static constexpr auto keyRotateDecr = 'z';
7static constexpr auto keyRotateIncr = 'x';
8static constexpr auto keyResizeInc = 'v';
9static constexpr auto keyWarpTestCycle = 'c';
10
11void printControls() {
12    printf("\n=== Controls:\n");
13    printf(" %c -rotated rectangle crop, decrease rate\n", keyRotateDecr);
14    printf(" %c -rotated rectangle crop, increase rate\n", keyRotateIncr);
15    printf(" %c -warp 4-point transform, cycle through modes\n", keyWarpTestCycle);
16    printf(" %c -resize cropped region, or disable resize\n", keyResizeInc);
17    printf(" h -print controls (help)\n");
18}
19
20static constexpr auto ROTATE_RATE_MAX = 5.0f;
21static constexpr auto ROTATE_RATE_INC = 0.1f;
22
23static constexpr auto RESIZE_MAX_W = 800;
24static constexpr auto RESIZE_MAX_H = 600;
25static constexpr auto RESIZE_FACTOR_MAX = 5;
26
27/* The crop points are specified in clockwise order,
28 * with first point mapped to output top-left, as:
29 *   P0  ->  P1
30 *    ^       v
31 *   P3  <-  P2
32 */
33static const dai::Point2f P0 = {0, 0};  // top-left
34static const dai::Point2f P1 = {1, 0};  // top-right
35static const dai::Point2f P2 = {1, 1};  // bottom-right
36static const dai::Point2f P3 = {0, 1};  // bottom-left
37struct warpFourPointTest {
38    std::vector<dai::Point2f> points;
39    bool normalizedCoords;
40    const char* description;
41};
42
43std::vector<warpFourPointTest> warpList = {
44    //{{{  0,  0},{  1,  0},{  1,  1},{  0,  1}}, true, "passthrough"},
45    //{{{  0,  0},{639,  0},{639,479},{  0,479}}, false,"passthrough (pixels)"},
46    {{P0, P1, P2, P3}, true, "1. passthrough"},
47    {{P3, P0, P1, P2}, true, "2. rotate 90"},
48    {{P2, P3, P0, P1}, true, "3. rotate 180"},
49    {{P1, P2, P3, P0}, true, "4. rotate 270"},
50    {{P1, P0, P3, P2}, true, "5. horizontal mirror"},
51    {{P3, P2, P1, P0}, true, "6. vertical flip"},
52    {{{-0.1f, -0.1f}, {1.1f, -0.1f}, {1.1f, 1.1f}, {-0.1f, 1.1f}}, true, "7. add black borders"},
53    {{{-0.3f, 0}, {1, 0}, {1.3f, 1}, {0, 1}}, true, "8. parallelogram transform"},
54    {{{-0.2f, 0}, {1.8f, 0}, {1, 1}, {0, 1}}, true, "9. trapezoid transform"},
55};
56
57int main() {
58    // Create pipeline
59    dai::Pipeline pipeline;
60
61    // Define sources and outputs
62    auto camRgb = pipeline.create<dai::node::ColorCamera>();
63    auto manip = pipeline.create<dai::node::ImageManip>();
64
65    auto camOut = pipeline.create<dai::node::XLinkOut>();
66    auto manipOut = pipeline.create<dai::node::XLinkOut>();
67    auto manipCfg = pipeline.create<dai::node::XLinkIn>();
68
69    camOut->setStreamName("preview");
70    manipOut->setStreamName("manip");
71    manipCfg->setStreamName("manipCfg");
72
73    // Properties
74    camRgb->setPreviewSize(640, 480);
75    camRgb->setResolution(dai::ColorCameraProperties::SensorResolution::THE_1080_P);
76    camRgb->setInterleaved(false);
77    camRgb->setColorOrder(dai::ColorCameraProperties::ColorOrder::BGR);
78    manip->setMaxOutputFrameSize(2000 * 1500 * 3);
79
80    // Linking
81    camRgb->preview.link(camOut->input);
82    camRgb->preview.link(manip->inputImage);
83    manip->out.link(manipOut->input);
84    manipCfg->out.link(manip->inputConfig);
85
86    // Connect to device and start pipeline
87    dai::Device device(pipeline);
88
89    // Create input & output queues
90    auto qPreview = device.getOutputQueue("preview", 8, false);
91    auto qManip = device.getOutputQueue("manip", 8, false);
92    auto qManipCfg = device.getInputQueue("manipCfg");
93
94    std::vector<decltype(qPreview)> frameQueues{qPreview, qManip};
95
96    // keep processing data
97    int key = -1;
98    float angleDeg = 0;
99    float rotateRate = 1.0;
100    int resizeFactor = 0;
101    int resizeX = 0;
102    int resizeY = 0;
103    bool testFourPt = false;
104    int warpIdx = -1;
105
106    printControls();
107
108    while(key != 'q') {
109        if(key >= 0) {
110            printf("Pressed: %c | ", key);
111            if(key == keyRotateDecr || key == keyRotateIncr) {
112                if(key == keyRotateDecr) {
113                    if(rotateRate > -ROTATE_RATE_MAX) rotateRate -= ROTATE_RATE_INC;
114                } else if(key == keyRotateIncr) {
115                    if(rotateRate < ROTATE_RATE_MAX) rotateRate += ROTATE_RATE_INC;
116                }
117                testFourPt = false;
118                printf("Crop rotated rectangle, rate: %g degrees", rotateRate);
119            } else if(key == keyResizeInc) {
120                resizeFactor++;
121                if(resizeFactor > RESIZE_FACTOR_MAX) {
122                    resizeFactor = 0;
123                    printf("Crop region not resized");
124                } else {
125                    resizeX = RESIZE_MAX_W / resizeFactor;
126                    resizeY = RESIZE_MAX_H / resizeFactor;
127                    printf("Crop region resized to: %d x %d", resizeX, resizeY);
128                }
129            } else if(key == keyWarpTestCycle) {
130                resizeFactor = 0;  // Disable resizing initially
131                warpIdx = (warpIdx + 1) % warpList.size();
132                printf("Warp 4-point transform: %s", warpList[warpIdx].description);
133                testFourPt = true;
134            } else if(key == 'h') {
135                printControls();
136            }
137            printf("\n");
138        }
139
140        // Send an updated config with continuous rotate, or after a key press
141        if(key >= 0 || (!testFourPt && std::abs(rotateRate) > 0.0001)) {
142            dai::ImageManipConfig cfg;
143            if(testFourPt) {
144                cfg.setWarpTransformFourPoints(warpList[warpIdx].points, warpList[warpIdx].normalizedCoords);
145            } else {
146                angleDeg += rotateRate;
147                dai::RotatedRect rr = {{320, 240},  // center
148                                       {640, 480},  //{400, 400}, // size
149                                       angleDeg};
150                cfg.setCropRotatedRect(rr, false);
151            }
152            if(resizeFactor > 0) {
153                cfg.setResize(resizeX, resizeY);
154            }
155            // cfg.setWarpBorderFillColor(255, 0, 0);
156            // cfg.setWarpBorderReplicatePixels();
157            qManipCfg->send(cfg);
158        }
159
160        for(const auto& q : frameQueues) {
161            auto img = q->get<dai::ImgFrame>();
162            auto mat = toMat(img->getData(), img->getWidth(), img->getHeight(), 3, 1);
163            cv::imshow(q->getName(), mat);
164        }
165        key = cv::waitKey(1);
166    }
167    return 0;
168}

需要帮助?

请前往 Discussion Forum 获取技术支持或提出您可能有的任何其他问题。