使用C ++ Actor Framewok和OpenCV

时间:2015-05-24 17:08:54

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

我正在尝试使用C ++ Actor Framework和OpenCV制作分布式视觉系统。我开始使用概念验证代码编译,但是在运行" edge"窗口已创建,但不显示任何内容(以下显示的代码)。

我真的不明白为什么它不起作用,任何帮助都会受到赞赏。

提前致谢。

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库

我使用MacOS X Yosemite和CLion 1.0.2作为IDE 运行程序时使用了大量的CPU资源:我第一次听到macbook的粉丝! CAF应该是一个轻量级框架,但也许我以错误的方式使用它。

1 个答案:

答案 0 :(得分:1)

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

演员应该是异步的,非阻塞的和合作的。 while (true)中的VideoCaptureActor循环阻止CAF调度程序中的工作线程。每次在不同的线程中调用imshow是否安全?因为这最终可能会发生在CannyActor。因此,它可能只是归结为OpenCV中的线程问题。

我建议做的第一件事是:

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

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

只要您不是通过网络发送图片,现在直接发送Mat(而不是宣布它)是安全的,看看是否使用{{来回转换1}}打破了一些东西。您还可以在将来的某个时间编写自定义序列化程序,以便直接序列化/反序列化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或类似的东西中以完全摆脱额外的副本(在额外的堆分配+间接的扩展中) )。

我希望有所帮助。