Skip to content

Commit

Permalink
This addresses and does close #11.
Browse files Browse the repository at this point in the history
  • Loading branch information
ethanrublee committed Sep 11, 2011
1 parent f83db38 commit 04e9d60
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 40 deletions.
181 changes: 141 additions & 40 deletions modules/opencv/highgui/imshow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <boost/format.hpp>
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>

#include <iostream>
#include <string>
Expand All @@ -23,12 +24,128 @@ namespace
{
*(x.second) = false;
}

};

}
namespace ecto_opencv
{
struct CloseWindow
{
CloseWindow(const std::string& name)
:
name(name)
{
}
void
operator()(const boost::signals2::connection& c) const
{
c.disconnect();
cv::destroyWindow(name);
}
std::string name;
};

struct ImshowJob
{
ImshowJob(const cv::Mat& image, const std::string& name, bool full_screen, bool auto_size)
:
image(image),
name(name),
full_screen(full_screen),
auto_size(auto_size)
{
}

void
operator()(const boost::signals2::connection& c) const
{
c.disconnect();
if (full_screen)
{
cv::namedWindow(name, CV_WINDOW_KEEPRATIO);
cv::setWindowProperty(name, CV_WND_PROP_FULLSCREEN, true);
}
else if (auto_size)
{
cv::namedWindow(name, CV_WINDOW_KEEPRATIO);
}
cv::imshow(name, image);
}
const cv::Mat image;
std::string name;
bool full_screen, auto_size;
};

struct HighGuiRunner
{
typedef boost::signals2::signal<void(void)> sig_type;
typedef boost::function<void(const boost::signals2::connection&)> jop_type;

HighGuiRunner()
:
lastKey(0xff)
{
t.reset(new boost::thread(boost::ref(*this)));
}

~HighGuiRunner()
{
t->interrupt();
t->join();
t.reset();
}

void
operator()()
{
while (!boost::this_thread::interruption_requested())
{
jobs();
lastKey = 0xff & cv::waitKey(10);
keys[lastKey] = true;
}
}

void
post_job(const jop_type& s)
{
sig_type::extended_slot_type job(s);
jobs.connect_extended(job);
}

bool
testKey(int time, unsigned char key, bool reset)
{
if (time > 0)
{
int count = 0;
while (lastKey == 0xff && count++ < time)
{
boost::this_thread::sleep(boost::posix_time::millisec(1));
}
}
else if (time == 0)
{
while (lastKey == 0xff)
{
boost::this_thread::sleep(boost::posix_time::millisec(1));
}
}
bool pressed = keys[key];
if (reset)
keys[key] = false;
return pressed;
}
unsigned char lastKey;
boost::shared_ptr<boost::thread> t;
sig_type jobs;
std::bitset<0xFF> keys;
}
;

namespace
{
boost::shared_ptr<HighGuiRunner> runner;
}
struct imshow
{
static void
Expand All @@ -45,17 +162,10 @@ namespace ecto_opencv
declare_io(const tendrils& params, tendrils& inputs, tendrils& outputs)
{
inputs.declare<cv::Mat>("image", "The image to show").required(true);
outputs.declare<int>("out", "Character pressed."); //optional output.

bp::object triggers;
params["triggers"] >> triggers;
if (!triggers || triggers == bp::object())
return;//no user supplied triggers.

if (params.get<int>("waitKey") < 0)
throw std::runtime_error(
"You may not have a waitKey of less than zero when you are supplying triggers."
" waitKey is what captures keypress events.");
return; //no user supplied triggers.

bp::list l = bp::dict(triggers).items();
for (int j = 0, end = bp::len(l); j < end; ++j)
Expand All @@ -76,12 +186,11 @@ namespace ecto_opencv
auto_size_ = params.get<bool>("autoSize");
full_screen_ = params["maximize"];
image_ = inputs["image"];
key_ = outputs["out"];

bp::object triggers;
params["triggers"] >> triggers;
if (!triggers || triggers == bp::object())
return; //no user supllied triggers.
return; //no user supplied triggers.

bp::list l = bp::dict(triggers).items();
for (int j = 0, end = bp::len(l); j < end; ++j)
Expand All @@ -98,21 +207,15 @@ namespace ecto_opencv
int
process(const tendrils& inputs, const tendrils& outputs)
{
if (!runner)
{
runner.reset(new HighGuiRunner);
}
cv::Mat image = *image_;
std::for_each(trigger_keys_.begin(), trigger_keys_.end(), trigger_reset());
*key_ = 0;
if (image.empty())
{
return 0;
}
if (*full_screen_)
{
cv::namedWindow(window_name_, CV_WINDOW_KEEPRATIO);
cv::setWindowProperty(window_name_, CV_WND_PROP_FULLSCREEN, true);
}
else if (auto_size_)
{
cv::namedWindow(window_name_, CV_WINDOW_KEEPRATIO);
return ecto::OK;
}

if (image.depth() == CV_32F || image.depth() == CV_64F)
Expand All @@ -131,33 +234,31 @@ namespace ecto_opencv
image = show;
}

cv::imshow(window_name_, image);

int r = 0;
if (waitkey_ >= 0)
r = 0xff & cv::waitKey(waitkey_);
runner->post_job(ImshowJob(image, window_name_, *full_screen_, auto_size_));

*key_ = r;

if (r == 27 || r == 'q' || r == 'Q')
if (runner->testKey(waitkey_, 'q', true) || runner->testKey(waitkey_, 27, true))
{
std::cout << "QUIT!\n";
runner->post_job(CloseWindow(window_name_));
return ecto::QUIT;
}
else
{
std::map<int, ecto::spore<bool> >::iterator it = trigger_keys_.find(r);
if (it != trigger_keys_.end())
*(it->second) = true;
return ecto::OK;
}
typedef std::pair<int, ecto::spore<bool> > KeySporeT;
BOOST_FOREACH(KeySporeT x, trigger_keys_)
{
*(x.second) = runner->testKey(waitkey_, x.first, true);
}
return ecto::OK;
}

~imshow()
{
runner->post_job(CloseWindow(window_name_));
}

std::string window_name_;
int waitkey_;
bool auto_size_;
ecto::spore<bool> full_screen_;
ecto::spore<cv::Mat> image_;
ecto::spore<int> key_;
std::map<int, ecto::spore<bool> > trigger_keys_;
};
}
Expand Down
20 changes: 20 additions & 0 deletions samples/rescale.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env python
import ecto
from ecto_opencv.highgui import VideoCapture, imshow, FPSDrawer
from ecto_opencv.imgproc import Scale, Interpolation
video_cap = VideoCapture(video_device=0, width=640, height=480)
fps = FPSDrawer()
factor = 0.1
scale_down = Scale(factor=factor, interpolation=Interpolation.AREA)
scale_up = Scale(factor=1 / factor, interpolation=Interpolation.LANCZOS4)

plasm = ecto.Plasm()
plasm.connect(video_cap['image'] >> scale_down['image'],
scale_down['image'] >> scale_up['image'],
scale_up['image'] >> fps['image'],
fps['image'] >> imshow(name='Rescaled',waitKey=100)['image'],
)

if __name__ == '__main__':
from ecto.opts import doit
doit(plasm, description='Capture a video from the device and display it.',locals=vars())

0 comments on commit 04e9d60

Please sign in to comment.