# 主机相机

本例演示如何在 DepthAI 管道中使用主机的摄像头（例如笔记本电脑摄像头），通过 HostCamera 节点实现。这使得您可以将网络摄像头（或连接到主机的任何其他摄像头）作为 DepthAI 管道的一部分来运行，从而利用 RVC 硬件的处理能力。

## 工作原理

HostCamera 类是一个自定义主机节点 (link)，它使用 OpenCV 从主机摄像头捕获帧。捕获的帧随后作为 ImgFrame 消息发送到 DepthAI 管道。管道随后可以使用其他节点（如神经网络、对象跟踪器等）处理这些帧。

HostCamera 节点是一个线程化的主机节点，这意味着它在主管道的单独线程中运行。这使得摄像头能够独立于管道的其余部分捕获帧，确保运行流畅。

这个示例需要DepthAI v3 API，参见[安装说明](https://docs.luxonis.com/software-v3/depthai.md)。

## 源代码

#### Python

```python
import depthai as dai
import cv2
import time

class HostCamera(dai.node.ThreadedHostNode):
    def __init__(self):
        super().__init__()
        self.output = self.createOutput()
    def run(self):
        # Create a VideoCapture object
        cap = cv2.VideoCapture(0)
        if not cap.isOpened():
            p.stop()
            raise RuntimeError("Error: Couldn't open host camera")
        while self.mainLoop():
            # Read the frame from the camera
            ret, frame = cap.read()
            if not ret:
                break
            # Create an ImgFrame message
            imgFrame = dai.ImgFrame()
            imgFrame.setData(frame)
            imgFrame.setWidth(frame.shape[1])
            imgFrame.setHeight(frame.shape[0])
            imgFrame.setType(dai.ImgFrame.Type.BGR888i)
            # Send the message
            self.output.send(imgFrame)
            # Wait for the next frame
            time.sleep(0.1)

with dai.Pipeline(createImplicitDevice=False) as p:
    hostCamera = p.create(HostCamera)
    camQueue = hostCamera.output.createOutputQueue()

    p.start()
    while p.isRunning():
        image : dai.ImgFrame = camQueue.get()
        cv2.imshow("HostCamera", image.getCvFrame())
        key = cv2.waitKey(1)
        if key == ord('q'):
            p.stop()
            break
```

#### C++

```cpp
#include <atomic>
#include <chrono>
#include <csignal>
#include <iostream>
#include <memory>
#include <opencv2/opencv.hpp>
#include <thread>

#include "depthai/depthai.hpp"

// Global flag for graceful shutdown
std::atomic<bool> quitEvent(false);

// Signal handler
void signalHandler(int signum) {
    quitEvent = true;
}

// Custom threaded host node for camera capture
class HostCamera : public dai::node::CustomThreadedNode<HostCamera> {
   public:
    HostCamera() {
        output = std::shared_ptr<dai::Node::Output>(new dai::Node::Output(*this, {"output", DEFAULT_GROUP, {{{dai::DatatypeEnum::ImgFrame, false}}}}));
    }

    void run() override {
        std::cout << "HostCamera running" << std::endl;
        // Create a VideoCapture object
        cv::VideoCapture cap(0);
        if(!cap.isOpened()) {
            std::cerr << "Error: Couldn't open host camera" << std::endl;
            stopPipeline();
            return;
        }

        while(mainLoop()) {
            // Read the frame from the camera
            cv::Mat frame;
            if(!cap.read(frame)) {
                break;
            }

            // Create an ImgFrame message
            auto imgFrame = std::make_shared<dai::ImgFrame>();

            std::vector<uchar> buffer(frame.data, frame.data + frame.total() * frame.elemSize());
            imgFrame->setData(buffer);
            imgFrame->setWidth(frame.cols);
            imgFrame->setHeight(frame.rows);
            imgFrame->setType(dai::ImgFrame::Type::BGR888i);

            // Send the message
            output->send(imgFrame);

            // Wait for the next frame
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }

        cap.release();
    }

    std::shared_ptr<dai::Node::Output> output;
};

int main() {
    // Set up signal handlers
    signal(SIGTERM, signalHandler);
    signal(SIGINT, signalHandler);

    // Create pipeline without implicit device
    dai::Pipeline pipeline(false);

    // Create host camera node
    auto hostCamera = pipeline.create<HostCamera>();
    auto camQueue = hostCamera->output->createOutputQueue();

    // Start pipeline
    pipeline.start();
    std::cout << "Host camera started. Press 'q' to quit." << std::endl;

    while(pipeline.isRunning() && !quitEvent) {
        auto image = camQueue->get<dai::ImgFrame>();
        if(image == nullptr) continue;

        cv::imshow("HostCamera", image->getCvFrame());

        int key = cv::waitKey(1);
        if(key == 'q') {
            pipeline.stop();
            break;
        }
    }

    // Cleanup
    pipeline.stop();
    pipeline.wait();

    return 0;
}
```

### 需要帮助？

请前往 [OAKChina 官网](https://www.oakchina.cn/) 获取技术支持或解答您的任何疑问。
