Skip to content

Commit

Permalink
Python 3 interface
Browse files Browse the repository at this point in the history
  • Loading branch information
gywn committed Nov 21, 2017
1 parent 3275137 commit 0965bd8
Show file tree
Hide file tree
Showing 15 changed files with 156 additions and 132 deletions.
43 changes: 24 additions & 19 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,34 +1,39 @@
cmake_minimum_required (VERSION 3.1)

project(color)
project(perception)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wconversion -Wno-unused-private-field -Wno-unused-variable -Wno-unused-parameter -fno-omit-frame-pointer -fsanitize=address")
set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_STATIC_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wconversion -Wno-unused-private-field -Wno-unused-variable -Wno-unused-parameter")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")

find_package(PythonLibs REQUIRED 3)
find_package(PythonInterp REQUIRED 3)
find_package(NumPy REQUIRED)
# find_package(PythonInterp REQUIRED 3)
# find_package(NumPy REQUIRED)

add_library(color SHARED src/debug.cpp src/conversion.cpp src/CIEDE2000.cpp src/fitness.cpp)
target_include_directories(color PUBLIC include PRIVATE ${PYTHON_INCLUDE_DIR} ${NUMPY_INCLUDE_DIR})
add_library(perception SHARED src/colorspace.cpp src/CIEDE2000.cpp src/fitness.cpp)
target_include_directories(perception PUBLIC include)

add_executable(testCIEDE2000 test/testCIEDE2000.cpp)
target_link_libraries(testCIEDE2000 color)
add_executable(testconversion test/testconversion.cpp)
target_link_libraries(testconversion color)
add_executable(testfitness test/testfitness.cpp)
target_link_libraries(testfitness color)
add_executable(testfitness2 test/testfitness2.cpp)
target_link_libraries(testfitness2 color)
add_library(pyperception MODULE src/python.cpp)
target_link_libraries(pyperception perception ${PYTHON_LIBRARIES})
target_include_directories(pyperception PRIVATE include ${PYTHON_INCLUDE_DIR})
set_target_properties(pyperception PROPERTIES PREFIX "")

add_executable(evo1 test/example1.cpp)
target_link_libraries(evo1 color)
add_executable(evo2 test/example2.cpp)
target_link_libraries(evo2 color)
add_executable(testevo1 test/example1.cpp)
target_link_libraries(testevo1 perception)
add_executable(testevo2 test/example2.cpp)
target_link_libraries(testevo2 perception)

add_executable(testlexi test/testlexi.cpp)
target_link_libraries(testlexi color)
target_link_libraries(testlexi perception)

add_executable(testCIEDE2000 test/testCIEDE2000.cpp)
target_link_libraries(testCIEDE2000 perception)
add_executable(testcolorspace test/testcolorspace.cpp)
target_link_libraries(testcolorspace perception)
add_executable(testfitness test/testfitness.cpp)
target_link_libraries(testfitness perception)
add_executable(testfitness2 test/testfitness2.cpp)
target_link_libraries(testfitness2 perception)
21 changes: 0 additions & 21 deletions LICENSE

This file was deleted.

11 changes: 4 additions & 7 deletions include/color.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
* See LICENSE for details.
*/

#ifndef GPF_COLOR_H_
#define GPF_COLOR_H_
#pragma once

#include <ostream>

Expand Down Expand Up @@ -62,8 +61,6 @@ RGB LABtoRGB(const LAB &lab);

} // namespace color

std::ostream &operator<<(std::ostream &s, const color::LAB &labColor);
std::ostream &operator<<(std::ostream &s, const color::XYZ &labColor);
std::ostream &operator<<(std::ostream &s, const color::RGB &labColor);

#endif /* GPF_COLOR_H_ */
std::ostream &operator<<(std::ostream &s, const color::LAB &lab);
std::ostream &operator<<(std::ostream &s, const color::XYZ &xyz);
std::ostream &operator<<(std::ostream &s, const color::RGB &rgb);
7 changes: 2 additions & 5 deletions include/constant.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#ifndef ICC_CONSTANT_H_
#define ICC_CONSTANT_H_
#pragma once

namespace color {
/* ICC's PCS illuminant */
Expand All @@ -17,6 +16,4 @@ const double A23 = -0.03294208;
const double A31 = -0.03269638;
const double A32 = -0.18259425;
const double A33 = 1.4716528;
} // namespace color

#endif /* ICC_CONSTANT_H_ */
} // namespace color
21 changes: 4 additions & 17 deletions include/fitness.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#ifndef FITNESS_H_
#define FITNESS_H_
#pragma once

#include "color.h"
#include "lexi.h"
Expand All @@ -14,25 +13,13 @@ LexiProduct<double> fitnessFunc(const std::vector<color::LAB> &lab);

class PerceptionResult {
public:
friend std::ostream &operator<<(std::ostream &os,
const PerceptionResult &res) {
os << "{" << std::endl << " flags: " << res.flags << std::endl;
os << " L: " << res.L << std::endl;
os << " rgb: [" << std::endl;
for (const auto &rgb : res.rgb)
os << " 0: " << rgb << std::endl;
os << " ]" << std::endl;
os << " fitness: " << res.fitness << std::endl << "}";
return os;
}

unsigned long flags;
double L;
std::vector<color::RGB> rgb;
LexiProduct<double> fitness;
};

PerceptionResult perceptionL(color::LAB foreground, color::LAB background,
size_t M, bool quiet = false);
std::ostream &operator<<(std::ostream &os, const PerceptionResult &res);

#endif
PerceptionResult perceptionL(color::LAB foreground, color::LAB background,
size_t M, bool quiet = false);
7 changes: 2 additions & 5 deletions include/lexi.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#ifndef LEXI_PRODUCT_H_
#define LEXI_PRODUCT_H_
#pragma once

#include <algorithm>
#include <ostream>
Expand Down Expand Up @@ -89,6 +88,4 @@ template <typename Scalar> class LexiProduct {
}
return lencmp;
}
};

#endif
};
1 change: 0 additions & 1 deletion src/CIEDE2000.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
*/

#include <cmath>

#include <color.h>

/*******************************************************************************
Expand Down
12 changes: 12 additions & 0 deletions src/conversion.cpp → src/colorspace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,15 @@ XYZ LABtoXYZ(const LAB &lab) {
RGB LABtoRGB(const LAB &lab) { return XYZtoRGB(LABtoXYZ(lab)); }

} // namespace color

std::ostream &operator<<(std::ostream &s, const color::LAB &lab) {
return (s << "LAB(" << lab.l << "," << lab.a << "," << lab.b << ")");
}

std::ostream &operator<<(std::ostream &s, const color::XYZ &xyz) {
return (s << "XYZ(" << xyz.x << "," << xyz.y << "," << xyz.z << ")");
}

std::ostream &operator<<(std::ostream &s, const color::RGB &rgb) {
return (s << "RGB(" << rgb.r << "," << rgb.g << "," << rgb.b << ")");
}
13 changes: 0 additions & 13 deletions src/debug.cpp

This file was deleted.

24 changes: 18 additions & 6 deletions src/fitness.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ LexiProduct<double> fitnessFunc(const std::vector<color::LAB> &lab) {
}

// number of combinations between colors, except the last two
size_t K = M * (M - 1) / 2 - 1;
size_t K = M * (M - 1) / 2 - 1;
static size_t cached_K = 0;
static std::vector<size_t> cached_ref; /* for almost-sorted O(n) sorting */
static std::vector<std::pair<size_t, size_t>> ref_combi;
Expand Down Expand Up @@ -87,6 +87,17 @@ void fill_lab(const std::vector<double> &x, std::vector<color::LAB> &lab,
}
}

std::ostream &operator<<(std::ostream &os, const PerceptionResult &res) {
os << "{" << std::endl << " flags: " << res.flags << std::endl;
os << " L: " << res.L << std::endl;
os << " rgb: [" << std::endl;
for (const auto &rgb : res.rgb)
os << " " << rgb << std::endl;
os << " ]" << std::endl;
os << " fitness: " << res.fitness << std::endl << "}";
return os;
}

/*
* @param foreground
* @param background
Expand Down Expand Up @@ -133,11 +144,12 @@ PerceptionResult perceptionL(color::LAB foreground, color::LAB background,

const auto xfinal = evo.getVector(CMAES<double, LexiProduct<double>>::XMean);
fill_lab(xfinal, lab, M);
std::sort(lab.begin(), lab.begin() + (long)M, [](const color::LAB &c1, const color::LAB &c2) {
const double h1 = std::atan2(-c1.b, -c1.a);
const double h2 = std::atan2(-c2.b, -c2.a);
return h1 < h2;
});
std::sort(lab.begin(), lab.begin() + (long)M,
[](const color::LAB &c1, const color::LAB &c2) {
const double h1 = std::atan2(-c1.b, -c1.a);
const double h2 = std::atan2(-c2.b, -c2.a);
return h1 < h2;
});
auto fitness = evo.getValue(CMAES<double, LexiProduct<double>>::FBestEver);

if (!quiet)
Expand Down
60 changes: 60 additions & 0 deletions src/python.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include <Python.h>
#include <color.h>
#include <fitness.h>
#include <iostream>

//< RAII wrapper for PyObject
class PyObj {
public:
PyObj() = delete;
PyObj(PyObject *ptr) : ptr(ptr){};
PyObj(const PyObj &obj) : ptr(obj.ptr) { Py_XINCREF(obj.ptr); };
PyObj(PyObj &&obj) : ptr(obj.ptr) { obj.ptr = nullptr; };
PyObj &operator=(const PyObj &obj) {
ptr = obj.ptr;
Py_XINCREF(ptr);
return *this;
};
PyObj &operator=(PyObj &&obj) {
ptr = obj.ptr;
obj.ptr = nullptr;
return *this;
};
~PyObj() { Py_XDECREF(ptr); };

PyObject *ptr;
};

static PyObject *perception(PyObject *self, PyObject *args) {
color::LAB fg, bg;
unsigned long M;
bool quiet;

if (!PyArg_ParseTuple(args, "(ddd)(ddd)k|p", &fg.l, &fg.a, &fg.b, &bg.l,
&bg.a, &bg.b, &M, &quiet))
return NULL;

const auto result = perceptionL(fg, bg, M, quiet);
PyObj rgb = PyObj(PyList_New(0));
for (const auto &c : result.rgb)
PyList_Append(rgb.ptr, PyObj(Py_BuildValue("(ddd)", c.r, c.g, c.b)).ptr);
PyObj fitness = PyObj(PyList_New(0));
for (const auto d : result.fitness.prd)
PyList_Append(fitness.ptr, PyObj(PyFloat_FromDouble(d)).ptr);

return Py_BuildValue("{sksdsOsO}", "flags", result.flags, "L", result.L,
"rgb", rgb.ptr, "fitness", fitness.ptr);
}

static PyMethodDef methods[] = {
{"perception", perception, METH_VARARGS,
"perception colors\n-----------------\n\n@param foreground "
"(l,a,b)\n@param background (l,a,b)\n@param M number of colors\n@param "
"quiet default:False"},
{NULL, NULL, 0, NULL}};

static struct PyModuleDef module = {
PyModuleDef_HEAD_INIT, "pyperception",
"Python interface for perception colors library", -1, methods};

PyMODINIT_FUNC PyInit_pyperception(void) { return PyModule_Create(&module); }
3 changes: 1 addition & 2 deletions test/testCIEDE2000.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@
*/

#include <cmath>
#include <color.h>
#include <iostream>
#include <string>
#include <vector>

#include <color.h>

/**
* @brief
* Run the test dataset run from the color paper.
Expand Down
3 changes: 1 addition & 2 deletions test/testconversion.cpp → test/testcolorspace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@
*/

#include <cmath>
#include <color.h>
#include <iostream>
#include <string>
#include <vector>

#include <color.h>

static size_t line = 0;
static std::vector<bool> passFail;

Expand Down
19 changes: 7 additions & 12 deletions test/testfitness.cpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
/*
* testcolor.cpp
* Part of http://github.com/gfiumara/color by Gregory Fiumara.
* See LICENSE for details.
*/

#include <cmath>
#include <color.h>
#include <fitness.h>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>

#include <color.h>
#include <fitness.h>

static size_t line = 0;
static std::vector<bool> passFail;

Expand All @@ -23,6 +17,7 @@ void check(bool res, const std::string &msg) {
}

void check(double a, double b, const std::string &msg, double delta = 1e-3) {
// std::cout << std::setprecision(10) << a << " " << b << std::endl;
check(std::abs(a - b) < delta, msg);
}

Expand Down Expand Up @@ -50,9 +45,9 @@ int testcolor() {
{50, 10, -10}})[0],
-12.8001, "fitnessFunc");

check(
fitnessFunc(std::vector<color::LAB>{{50, -200, -200}, {50, 200, 200}})[0],
1626.445599, "fitnessFunc (off boundary)");
check(fitnessFunc(std::vector<color::LAB>{
{50, -200, -200}, {50, 200, 200}, {50, 0, 0}, {50, 0, 0}})[0],
3337.715201, "fitnessFunc (off boundary)");

std::cout << std::endl;
int ret = EXIT_SUCCESS;
Expand Down
Loading

0 comments on commit 0965bd8

Please sign in to comment.