Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
aaalgo committed Jul 19, 2016
1 parent 4ff50bc commit 2363b08
Show file tree
Hide file tree
Showing 6 changed files with 275 additions and 82 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ SERVER_LIBS = -lserved -lmagic
HEADERS = picpac.h picpac-cv.h picpac-util.h
COMMON = picpac-util.o picpac-cv.o picpac.o json11.o

PROGS = picpac-import-cifar picpac-import-nmist test stress picpac-import picpac-stream picpac-server picpac-proto picpac-roi-scale #picpac-stat picpac-annotate picpac-dumpvec#load-caffe load-dir test test_tr server
PROGS = picpac-dupe picpac-import-cifar picpac-import-nmist test stress picpac-import picpac-stream picpac-server picpac-proto picpac-roi-scale #picpac-stat picpac-annotate picpac-dumpvec#load-caffe load-dir test test_tr server

.PHONY: all release python upload_test upload sdist

Expand Down
189 changes: 119 additions & 70 deletions picpac-cv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,30 @@ namespace picpac {
}


class Shape {
public:
virtual void draw (cv::Mat *, cv::Scalar v, int thickness = CV_FILLED) const = 0;
virtual void bbox (cv::Rect_<float> *) const = 0;
static std::shared_ptr<Shape> create (Json const &geo);
};

class Box: public Shape {
protected:
cv::Rect_<float> rect;
public:
Box (Json const &geo) {
Box (Json const &geo, char const *t = "rect"): Shape(t) {
rect.x = geo["x"].number_value();
rect.y = geo["y"].number_value();
rect.width = geo["width"].number_value();
rect.height = geo["height"].number_value();
}
virtual void dump (Json *json) const {
*json = Json::object {
{"type", type()},
{"geometry", Json::object{
{"x", rect.x},
{"y", rect.y},
{"width", rect.width},
{"height", rect.height}
}}
};
}
virtual std::shared_ptr<Shape> clone () const {
return std::shared_ptr<Shape>(new Box(*this));
}
virtual void draw (cv::Mat *m, cv::Scalar v, int thickness) const {
cv::Rect box;
box.x = std::round(m->cols * rect.x);
Expand All @@ -61,36 +69,52 @@ namespace picpac {
virtual void bbox (cv::Rect_<float> *bb) const {
*bb = rect;
}
virtual void zoom (cv::Rect_<float> const &bb) {
rect.x -= bb.x;
rect.y -= bb.y;
rect.x /= bb.width;
rect.width /= bb.width;
rect.y /= bb.height;
rect.height /= bb.height;
}
};

class Ellipse: public Shape {
cv::Rect_<float> rect;
class Ellipse: public Box {
public:
Ellipse (Json const &geo) {
rect.x = geo["x"].number_value();
rect.y = geo["y"].number_value();
rect.width = geo["width"].number_value();
rect.height = geo["height"].number_value();
Ellipse (Json const &geo): Box(geo, "ellipse") {
}
virtual std::shared_ptr<Shape> clone () const {
return std::shared_ptr<Shape>(new Ellipse(*this));
}
virtual void draw (cv::Mat *m, cv::Scalar v, int thickness) const {
cv::Point2f center(m->cols * (rect.x + rect.width/2),
m->rows * (rect.y + rect.height/2));
cv::Size2f size(m->cols * rect.width, m->rows * rect.height);
cv::ellipse(*m, cv::RotatedRect(center, size, 0), v, thickness);
}
virtual void bbox (cv::Rect_<float> *bb) const {
*bb = rect;
}
};

class Poly: public Shape {
vector<cv::Point2f> points;
public:
Poly (Json const &geo) {
Poly (Json const &geo): Shape("polygon") {
for (auto const &p: geo["points"].array_items()) {
points.emplace_back(p["x"].number_value(), p["y"].number_value());
}
}
virtual void dump (Json *json) const {
vector<Json> pts;
for (auto const &p: points) {
pts.emplace_back(Json::object{{"x", p.x}, {"y", p.y}});
}
*json = Json::object {
{"type", type()},
{"geometry", Json::object{{"points", pts}}}
};
}
virtual std::shared_ptr<Shape> clone () const {
return std::shared_ptr<Poly>(new Poly(*this));
}
virtual void draw (cv::Mat *m, cv::Scalar v, int thickness) const {
vector<cv::Point> ps(points.size());
for (unsigned i = 0; i < ps.size(); ++i) {
Expand Down Expand Up @@ -128,6 +152,14 @@ namespace picpac {
bb->height = max_y - min_y;
}
}
virtual void zoom (cv::Rect_<float> const &bb) {
for (auto &p: points) {
p.x -= bb.x;
p.y -= bb.y;
p.x /= bb.width;
p.y /= bb.height;
}
}
};

std::shared_ptr<Shape> Shape::create (Json const &geo) {
Expand All @@ -145,57 +177,68 @@ namespace picpac {
return 0;
}

class Annotation {
vector<std::shared_ptr<Shape>> shapes;
public:
Annotation () {}
Annotation (string const &txt) {
string err;
Json json = Json::parse(txt, err);
if (err.size()) {
LOG(ERROR) << "Bad json: " << err << " (" << txt << ")";
return;
}
for (auto const &x: json["shapes"].array_items()) {
shapes.emplace_back(Shape::create(x));
}
Annotation::Annotation (string const &txt) {
string err;
Json json = Json::parse(txt, err);
if (err.size()) {
LOG(ERROR) << "Bad json: " << err << " (" << txt << ")";
return;
}
for (auto const &x: json["shapes"].array_items()) {
shapes.emplace_back(Shape::create(x));
}
}

void draw (cv::Mat *m, cv::Scalar v, int thickness = -1) const {
for (auto const &p: shapes) {
p->draw(m, v, thickness);
}
void Annotation::dump (string *str) const {
vector<Json> ss;
for (auto const &p: shapes) {
Json json;
p->dump(&json);
ss.emplace_back(std::move(json));
}
Json json = Json::object {{"shapes", ss}};
*str = json.dump();
}

void bbox (cv::Rect_<float> *bb) const {
float min_x = 1, min_y = 1;
float max_x = 0, max_y = 0;
for (auto const &p: shapes) {
cv::Rect_<float> sb;
p->bbox(&sb);
if (sb.area() <= 0) continue;
void Annotation::draw (cv::Mat *m, cv::Scalar v, int thickness) const {
for (auto const &p: shapes) {
p->draw(m, v, thickness);
}
}

if (sb.x < min_x) min_x = sb.x;
if (sb.y < min_y) min_y = sb.y;
void Annotation::bbox (cv::Rect_<float> *bb) const { float min_x = 1, min_y = 1;
float max_x = 0, max_y = 0;
for (auto const &p: shapes) {
cv::Rect_<float> sb;
p->bbox(&sb);
if (sb.area() <= 0) continue;

sb.x += sb.width;
sb.y += sb.height;
if (sb.x < min_x) min_x = sb.x;
if (sb.y < min_y) min_y = sb.y;

if (sb.x > max_x) max_x = sb.x;
if (sb.y > max_y) max_y = sb.y;
}
float area = (max_x - min_x) * (max_y - min_y);
if (area <= 0) {
*bb = cv::Rect_<float>();
}
else {
bb->x = min_x;
bb->y = min_y;
bb->width = max_x - min_x;
bb->height = max_y - min_y;
}
sb.x += sb.width;
sb.y += sb.height;

if (sb.x > max_x) max_x = sb.x;
if (sb.y > max_y) max_y = sb.y;
}
};
float area = (max_x - min_x) * (max_y - min_y);
if (area <= 0) {
*bb = cv::Rect_<float>();
}
else {
bb->x = min_x;
bb->y = min_y;
bb->width = max_x - min_x;
bb->height = max_y - min_y;
}
}

void Annotation::zoom (cv::Rect_<float> const &bb) {
for (auto &p: shapes) {
p->zoom(bb);
}
}

// for visualization only!!!
void spectrogram_to_gray (cv::Mat m, cv::Mat *gray) {
Expand Down Expand Up @@ -261,14 +304,7 @@ namespace picpac {
rr(&r); // disk access
cached.label = r.meta().label;
//CHECK(r.size() >= (annotate ? 2 : 1));
auto imbuf = r.field(0);
cached.image = cv::imdecode(cv::Mat(1, boost::asio::buffer_size(imbuf), CV_8U,
const_cast<void *>(boost::asio::buffer_cast<void const *>(imbuf))),
config.decode_mode);
if (!cached.image.data) {
cached.image = decode_raw(boost::asio::buffer_cast<char const *>(imbuf),
boost::asio::buffer_size(imbuf));
}
cached.image = decode_buffer(r.field(0), config.decode_mode);
if ((config.channels > 0) && config.channels != cached.image.channels()) {
cv::Mat tmp;
if (cached.image.channels() == 3 && config.channels == 1) {
Expand Down Expand Up @@ -605,5 +641,18 @@ namespace picpac {
}
return m;
}

cv::Mat decode_buffer (const_buffer imbuf, int mode) {
cv::Mat image = cv::imdecode(cv::Mat(1, boost::asio::buffer_size(imbuf), CV_8U,
const_cast<void *>(boost::asio::buffer_cast<void const *>(imbuf))),
mode);
if (!image.data) {
image = decode_raw(boost::asio::buffer_cast<char const *>(imbuf),
boost::asio::buffer_size(imbuf));
}
return image;
}


}

31 changes: 30 additions & 1 deletion picpac-cv.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@
PICPAC_CONFIG_UPDATE(C,pad);\
PICPAC_CONFIG_UPDATE(C,bgr2rgb);

namespace json11 {
class Json;
}

namespace picpac {

Expand Down Expand Up @@ -439,6 +442,7 @@ namespace picpac {
}
};

cv::Mat decode_buffer (const_buffer, int mode);
void encode_raw (cv::Mat, string *);
cv::Mat decode_raw (char const *, size_t);

Expand All @@ -448,7 +452,6 @@ namespace picpac {
public:
ImageEncoder (string const &code_ = string()): code(code_) {
}

void encode (cv::Mat const &image, string *);
};

Expand All @@ -469,5 +472,31 @@ namespace picpac {
static inline float LimitSize (cv::Mat input, int max_size, cv::Mat *output) {
return LimitSize(input, -1, max_size, output);
}

class Shape {
string _type;
public:
Shape (char const *t): _type(t) {}
virtual ~Shape () {}
virtual void draw (cv::Mat *, cv::Scalar v, int thickness = CV_FILLED) const = 0;
virtual void bbox (cv::Rect_<float> *) const = 0;
virtual void zoom (cv::Rect_<float> const &) = 0;
virtual void dump (json11::Json *) const = 0;
string const &type () const {
return _type;
}
virtual std::shared_ptr<Shape> clone () const = 0;
static std::shared_ptr<Shape> create (json11::Json const &geo);
};

struct Annotation {
vector<std::shared_ptr<Shape>> shapes;
Annotation () {}
Annotation (string const &txt);
void dump (string *) const;
void draw (cv::Mat *m, cv::Scalar v, int thickness = -1) const;
void bbox (cv::Rect_<float> *bb) const;
void zoom (cv::Rect_<float> const &bb);
};
}

Loading

0 comments on commit 2363b08

Please sign in to comment.