Commit b28c92dc authored by André Anjos's avatar André Anjos 💬
Browse files

Box drawing incorporated; All tests now passing

parent 711462c6
......@@ -45,10 +45,11 @@ setup(
),
Extension("xbob.ip.draw._library",
[
"xbob/ip/draw/cross.cpp",
"xbob/ip/draw/line.cpp",
"xbob/ip/draw/try_point.cpp",
"xbob/ip/draw/point.cpp",
"xbob/ip/draw/try_point.cpp",
"xbob/ip/draw/line.cpp",
"xbob/ip/draw/cross.cpp",
"xbob/ip/draw/box.cpp",
"xbob/ip/draw/main.cpp",
],
packages = packages,
......
/**
* @author André Anjos <andre.anjos@idiap.ch>
* @date Tue 8 Apr 09:34:47 2014 CEST
*
* @brief Binds box drawing operator to Python
*
* Copyright (C) 2011-2014 Idiap Research Institute, Martigny, Switzerland
*/
#include <xbob.blitz/cppapi.h>
#include <xbob.blitz/cleanup.h>
#include <boost/tuple/tuple.hpp>
#include <bob/ip/drawing.h>
#include "utils.h"
template <typename T>
static PyObject* inner_box (PyBlitzArrayObject* image,
Py_ssize_t y, Py_ssize_t x, Py_ssize_t h, Py_ssize_t w, PyObject* color) {
switch (image->ndim) {
case 2:
{
T c;
int ok = get_color1(color, c);
if (!ok) return 0;
try {
bob::ip::draw_box(*PyBlitzArrayCxx_AsBlitz<T,2>(image), y, x,
h, w, c);
}
catch (std::exception& e) {
PyErr_Format(PyExc_RuntimeError, "%s", e.what());
return 0;
}
catch (...) {
PyErr_SetString(PyExc_RuntimeError, "caught unknown exception while calling C++ bob::ip::draw_box");
return 0;
}
}
break;
case 3:
{
T r, g, b;
int ok = get_color3(color, r, g, b);
if (!ok) return 0;
try {
bob::ip::draw_box(*PyBlitzArrayCxx_AsBlitz<T,3>(image), y, x,
h, w, boost::tuple<T,T,T>(r, g, b));
}
catch (std::exception& e) {
PyErr_Format(PyExc_RuntimeError, "%s", e.what());
return 0;
}
catch (...) {
PyErr_SetString(PyExc_RuntimeError, "caught unknown exception while calling C++ bob::ip::draw_box");
return 0;
}
}
break;
default:
PyErr_Format(PyExc_TypeError, "drawing operation does not support images with %" PY_FORMAT_SIZE_T "d dimensions (1 or 3 only)", image->ndim);
return 0;
}
Py_RETURN_NONE;
}
PyObject* PyBobIpDraw_Box (PyObject*, PyObject* args, PyObject* kwds) {
static const char* const_kwlist[] = {"image", "p", "size", "color", 0};
static char** kwlist = const_cast<char**>(const_kwlist);
PyBlitzArrayObject* image = 0;
Py_ssize_t y, x, h, w;
PyObject* color = 0;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&(nn)(nn)O", kwlist,
&PyBlitzArray_OutputConverter, &image,
&y, &x, &h, &w, &color)) return 0;
//protects acquired resources through this scope
auto image_ = make_safe(image);
switch(image->type_num) {
case NPY_UINT8:
return inner_box<uint8_t>(image, y, x, h, w, color);
case NPY_UINT16:
return inner_box<uint16_t>(image, y, x, h, w, color);
case NPY_FLOAT64:
return inner_box<double>(image, y, x, h, w, color);
default:
PyErr_Format(PyExc_TypeError, "drawing operation does not support images with data type `%s' (choose from uint8|uint16|float64)", PyBlitzArray_TypenumAsString(image->type_num));
}
return 0;
}
......@@ -2,7 +2,7 @@
* @author André Anjos <andre.anjos@idiap.ch>
* @date Mon 7 Apr 14:50:46 2014 CEST
*
* @brief Binds point drawing operator to Python
* @brief Binds cross drawing operators to Python
*
* Copyright (C) 2011-2014 Idiap Research Institute, Martigny, Switzerland
*/
......
......@@ -2,7 +2,7 @@
* @author André Anjos <andre.anjos@idiap.ch>
* @date Mon 7 Apr 17:57:11 2014 CEST
*
* @brief Binds point drawing operator to Python
* @brief Binds line drawing operator to Python
*
* Copyright (C) 2011-2014 Idiap Research Institute, Martigny, Switzerland
*/
......
......@@ -149,9 +149,38 @@ static xbob::extension::FunctionDoc s_plus = xbob::extension::FunctionDoc(
.add_parameter("color", "scalar|tuple", "Color of the cross sign. In case the input image is gray-scale (2D), this should be a single scalar. If the input image is colored (3D), then it should be a sequence containing 3 scalars, representing the levels of red, green and blue (in this order) of the pixel to be drawn. The type of scalars representing colors should match the pixel type in ``image``.")
;
/**
def("draw_box", &draw_box, (arg("image"), arg("y"), arg("x"), arg("height"), arg("width"), arg("color")), "Draws a box at the image using the draw_line() primitive. This method supports both grayscale (2D) or color RGB (3D) images. Depending on your image type, select an appropriate color value: a single gray value for 2D grayscale images or a 3-tuple containing the RGB color to set during drawing.");
**/
extern PyObject* PyBobIpDraw_Box(PyObject*, PyObject* args, PyObject* kwds);
static xbob::extension::FunctionDoc s_box = xbob::extension::FunctionDoc(
"box",
"Draws a box anchored at a point, with the given dimensions.",
"This method draws a box, using the :py:func:`line` primitives, into the "
"provided image. The box will be anchored at a given point, which refers "
"to its upper-left corner and have a certain size, defined in terms of "
"its height and width.\n"
"\n"
"The line may go out of the image bounds in which case such points "
"(lying outside the image boundary) are ignored.\n"
"\n"
"See also: http://en.wikipedia.org/wiki/Bresenham's_line_algorithm.\n"
"\n"
"This function can work with either gray-scale or color images. "
"In case you pass a 2D array representing a gray-scale image, this function "
"expects you pass a single scalar as a value for the input parameter "
"``color``. In the case you pass a 3D array (color image), then the color "
"parameter should be set to a tuple contanining 3 scalars representing the "
"levels for each of the color components (red, green and blue)\n"
"\n"
)
.add_prototype("image, p, size, color")
.add_parameter("image", "array (uint8|uint16|float64, 3D)", "Input array containing an image with the shape ``(height, width)`` (for gray-scale images) or ``(3, height, width)`` (for color images)")
.add_parameter("p", "tuple", "a point, on the format ``(y, x)``, defining the location on the image of the **upper-left** corner of the box.")
.add_parameter("size", "tuple", "a tuple of integers on the format ``(height, width)`` indicating the size of the box.")
.add_parameter("color", "scalar|tuple", "Color of the pixel. In case the input image is gray-scale (2D), this should be a single scalar. If the input image is colored (3D), then it should be a sequence containing 3 scalars, representing the levels of red, green and blue (in this order) of the pixel to be drawn. The type of scalars representing colors should match the pixel type in ``image``.")
;
static PyMethodDef module_methods[] = {
{
......@@ -184,6 +213,12 @@ static PyMethodDef module_methods[] = {
METH_VARARGS|METH_KEYWORDS,
s_plus.doc()
},
{
s_box.name(),
(PyCFunction)PyBobIpDraw_Box,
METH_VARARGS|METH_KEYWORDS,
s_box.doc()
},
{0} /* Sentinel */
};
......
......@@ -11,7 +11,7 @@
import numpy
import nose.tools
from . import point, try_point, line, cross, plus#, box
from . import point, try_point, line, cross, plus, box
def test_gray_point():
......@@ -128,7 +128,7 @@ def test_box():
image.fill(0)
# Draws a white line on the middle (horizontal)
box(image, 50, 50, 20, 20, 255)
box(image, (50, 50), (20, 20), 255)
for k in range(50,70):
nose.tools.eq_(image[k,50], 255)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment