0

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

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

提前致谢。

PS 代码

主文件

#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 应该是一个轻量级框架,但也许我以错误的方式使用它。

4

1 回答 1

1

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

Actor 应该是异步的、非阻塞的和协作的。while (true)循环阻塞 CAF 调度程序中的VideoCaptureActor工作线程。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没有移动构造函数,您可以将帧存储在 astd::shared_ptr<Mat>或类似的东西中以完全摆脱额外的副本(在额外的堆分配+间接的扩展)。

我希望这会有所帮助。

于 2015-05-29T10:31:23.843 回答