【问题标题】:Using the C++ Actor Framewok with OpenCV将 C++ Actor 框架与 OpenCV 结合使用
【发布时间】:2015-08-06 05:06:14
【问题描述】:

我正在尝试使用 C++ Actor Framework 和 OpenCV 创建一个分布式视觉系统。我从一个可编译的概念验证代码开始,但在运行时会创建“边缘”窗口但不显示任何内容(代码如下所示)。

我真的不明白为什么它不起作用,任何帮助将不胜感激。

提前致谢。

PS 代码

main.cpp

#include <vector>
#include "opencv2/opencv.hpp"

#include "caf/all.hpp"

using namespace cv;
using namespace caf;
using namespace std;

struct Image {
    Image(Mat mat = Mat()) {
        data.assign(mat.datastart,mat.dataend);
        type = mat.type();
        rows = mat.rows;
        cols = mat.cols;
    }

    Mat toMat() const {
        return Mat(rows,cols,type,(void *)data.data());
    }

    vector<uchar> data;
    int type;
    int rows;
    int cols;
};

bool operator==(const Image& lhs, const Image& rhs) {
    return  lhs.data == rhs.data
            && lhs.type == rhs.type
               && lhs.rows == rhs.rows
                  && lhs.cols == rhs.cols;
}

class VideoCaptureActor : public event_based_actor{
    VideoCapture cap;
    actor buddy;
protected:
    behavior make_behavior() override {
        send(this,get_atom::value);
        return {
                [=](get_atom){
                    while(true){
                        Mat frame;
                        cap >> frame;
                        this->send(buddy,put_atom::value,Image(frame));
                        if(waitKey(60) >= 0){
                            send(this,ok_atom::value);
                            break;
                        }
                    }
                },
                [=](ok_atom){
                    cout << "Hello "<< buddy.id() <<" !"<<endl;
                },
                others >> [=](){
                    cerr << "unexpected: " << to_string(this->current_message()) << buddy.id() << endl;
                }

        };
    }

public:
    VideoCaptureActor(const actor &buddy){
        this->buddy = buddy;
        cap.open(0);
        if(!cap.isOpened())
            throw -1;
    }
};

class CannyActor : public event_based_actor {
    Mat edges;
protected:
    behavior make_behavior() override {
        return {
                [=](put_atom,Image image){
                    cvtColor(image.toMat(), edges, CV_BGR2GRAY);
                    GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5);
                    Canny(edges, edges, 0, 30, 3);
                    imshow("edges", edges);
                },
                others >> [=] {
                    cerr << "unexpected: " << to_string(this->current_message()) << endl;
                }

        };
    }
public:
    CannyActor(){
        namedWindow("edges",1);
    }
};

int main(int, char**) {
    announce<Image>("Image",&Image::data,&Image::type,&Image::rows,&Image::cols);
    try {
        spawn<VideoCaptureActor>(spawn<CannyActor>());
    }catch(int x){
        cerr<<x<<endl;
    }
    await_all_actors_done();
    shutdown();
    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.2)
project(SmartVision CXX)

set (CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})

find_package(OpenCV REQUIRED)
find_package(Libcaf COMPONENTS core io REQUIRED)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11  -Wextra -Wall -pedantic")
set(CMAKE_CXX_FLAGS_DEBUG          "-O0 -g")
set(CMAKE_CXX_FLAGS_MINSIZEREL     "-Os")
set(CMAKE_CXX_FLAGS_RELEASE        "-O4")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")

include_directories(${OpenCV_INCLUDE_DIRS} ${LIBCAF_INCLUDE_DIRS})
set(SOURCE_FILES main.cpp)
add_executable(SmartVision ${SOURCE_FILES})
target_link_libraries(SmartVision ${OpenCV_LIBS} ${LIBCAF_LIBRARIES})

我还将 FindLibcaf.cmake 文件放在我的项目根文件夹中,以使 cmake 能够找到 CAF 库

我正在使用带有 CLion 1.0.2 的 MacOS X Yosemite 作为 IDE 运行程序时使用大量 CPU 资源:我第一次听到我的 macbook 运行时的风扇! CAF 应该是一个轻量级的框架,但可能我用错了。

【问题讨论】:

    标签: c++ opencv actor distributed-computing c++-actor-framework


    【解决方案1】:

    免责声明:我没有使用 OpenCV 的经验。所以我只能帮助弄清楚 CAF 方面发生了什么。

    Actor 应该是异步的、非阻塞的和协作的。 VideoCaptureActor 中的 while (true) 循环阻塞了 CAF 调度程序中的工作线程。每次在不同的线程中调用imshow 是否安全?因为这是CannyActor 最终可能发生的事情。所以它可能只是归结为 OpenCV 中的线程问题。

    我建议做的第一件事是:

    spawn<VideoCaptureActor, detached>(spawn<CannyActor, detached>());
    

    这将为您的两个演员中的每一个分配一个专用线程。

    只要您不通过网络发送图像,现在直接发送Mat(而不是宣布它)是安全的,看看与Image 的来回转换是否失败某物。您还可以在将来的某个时间编写自定义序列化程序,允许您直接序列化/反序列化Mat

    [=](get_atom) {
      while (true) {
        Mat frame;
        cap >> frame;
        send(buddy, put_atom::value, std::move(frame));
        if(waitKey(60) >= 0){
          send(this, ok_atom::value);
          break;
        }
      }
    },
    

    如果 Mat 没有移动构造函数,您可以将帧存储在 std::shared_ptr&lt;Mat&gt; 或类似的东西中以完全摆脱额外的副本(在额外的堆分配 + 间接的扩展)。

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 2019-03-24
      • 1970-01-01
      • 1970-01-01
      • 2016-09-12
      • 1970-01-01
      • 2011-09-29
      • 1970-01-01
      • 1970-01-01
      • 2011-08-19
      相关资源
      最近更新 更多