Я пытаюсь создать систему распределенного зрения с использованием 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
Я использую MacOS X Yosemite с CLion 1.0.2 в качестве IDE
При запуске программы используется много ресурсов ЦП: я впервые услышал, как работает мой macbook, когда он запускается! CAF должен быть легковесным фреймворком, но, возможно, я неправильно его использую.
Отказ от ответственности: у меня нет опыта работы с OpenCV. Так что я могу только помочь понять, что происходит на стороне CAF.
Актеры должны быть асинхронными, неблокирующими и кооперативными. while (true)
зациклиться VideoCaptureActor
блокирует рабочий поток в планировщике 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<Mat>
или что-то в этом роде, чтобы полностью избавиться от лишней копии (при дополнительном выделении кучи + косвенное указание).
Надеюсь, это поможет.