Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generalization: Switch from using CImg to OpenCV library. #2084

Merged
merged 1 commit into from
Sep 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/actions/ubuntu-prerequisites/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ runs:
- name: Install software
run: |
sudo apt-get install -yq --no-install-suggests --no-install-recommends \
cimg-dev \
libboost-filesystem-dev \
libboost-system-dev \
libbz2-dev \
libexpat1-dev \
libopencv-core-dev \
libopencv-imgcodecs-dev \
libopencv-imgproc-dev \
libpotrace-dev \
libpq-dev \
libproj-dev \
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/win-install/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ runs:
boost-property-tree:x64-windows \
boost-system:x64-windows \
bzip2:x64-windows \
cimg:x64-windows \
expat:x64-windows \
libpq:x64-windows \
lua:x64-windows \
nlohmann-json:x64-windows \
opencv:x64-windows \
proj4:x64-windows \
zlib:x64-windows
shell: bash
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:

- name: Install prerequisites
run: |
brew install lua boost postgis pandoc cimg potrace nlohmann-json
brew install boost lua nlohmann-json opencv pandoc postgis potrace
pip3 install psycopg2 behave osmium
pg_ctl -D /usr/local/var/postgres init
pg_ctl -D /usr/local/var/postgres start
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/test-install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@ jobs:
sudo apt-get purge -yq postgresql*
sudo apt-get update -qq
sudo apt-get install -yq --no-install-suggests --no-install-recommends \
cimg-dev \
libboost-filesystem-dev \
libboost-system-dev \
libbz2-dev \
libexpat1-dev \
liblua${LUA_VERSION}-dev \
libluajit-5.1-dev \
libopencv-core-dev \
libopencv-imgcodecs-dev \
libopencv-imgproc-dev \
libpotrace-dev \
libpq-dev \
libproj-dev \
Expand Down
11 changes: 5 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ include_directories(SYSTEM ${NLOHMANN_INCLUDE_DIR})
find_path(POTRACE_INCLUDE_DIR potracelib.h)
find_library(POTRACE_LIBRARY NAMES potrace)

find_path(CIMG_INCLUDE_DIR CImg.h)
find_package(OpenCV OPTIONAL_COMPONENTS core imgcodecs imgproc)

############### Libraries are found now ########################

Expand Down Expand Up @@ -284,13 +284,12 @@ add_subdirectory(src)
add_executable(osm2pgsql src/osm2pgsql.cpp)
target_link_libraries(osm2pgsql osm2pgsql_lib ${LIBS})

if (${POTRACE_LIBRARY} STREQUAL "POTRACE_LIBRARY-NOTFOUND" OR ${CIMG_INCLUDE_DIR} STREQUAL "CIMG_INCLUDE_DIR-NOTFOUND")
message(STATUS "Did not find cimg and/or potrace library. Not building osm2pgsql-gen.")
if (${POTRACE_LIBRARY} STREQUAL "POTRACE_LIBRARY-NOTFOUND" OR NOT OPENCV_CORE_FOUND)
message(STATUS "Did not find opencv and/or potrace library. Not building osm2pgsql-gen.")
else()
if (WITH_LUA)
message(STATUS "Found cimg and potrace library. Building osm2pgsql-gen.")
message(STATUS "Found opencv and potrace library. Building osm2pgsql-gen.")
set(BUILD_GEN 1)
include_directories(SYSTEM ${CIMG_INCLUDE_DIR})
include_directories(SYSTEM ${POTRACE_INCLUDE_DIR})
add_executable(osm2pgsql-gen src/gen/osm2pgsql-gen.cpp
src/gen/canvas.cpp
Expand All @@ -305,7 +304,7 @@ else()
src/gen/params.cpp
src/gen/raster.cpp
src/gen/tracer.cpp)
target_link_libraries(osm2pgsql-gen osm2pgsql_lib ${LIBS} ${POTRACE_LIBRARY})
target_link_libraries(osm2pgsql-gen osm2pgsql_lib ${LIBS} ${POTRACE_LIBRARY} ${OpenCV_LIBS})
else()
message(STATUS "No Lua. Not building osm2pgsql-gen.")
endif()
Expand Down
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Required libraries are
* [Boost libraries](https://www.boost.org/), including geometry, system and
filesystem
* [nlohmann/json](https://json.nlohmann.me/)
* [CImg](https://cimg.eu/) (Optional, for generalization only)
* [OpenCV](https://opencv.org/) (Optional, for generalization only)
* [potrace](https://potrace.sourceforge.net/) (Optional, for generalization only)
* [PostgreSQL](https://www.postgresql.org/) client libraries
* [Lua](https://www.lua.org/) (Optional, used for Lua tag transforms
Expand Down Expand Up @@ -83,7 +83,8 @@ On a Debian or Ubuntu system, this can be done with:

```sh
sudo apt-get install make cmake g++ libboost-dev libboost-system-dev \
libboost-filesystem-dev libexpat1-dev zlib1g-dev libpotrace-dev cimg-dev \
libboost-filesystem-dev libexpat1-dev zlib1g-dev libpotrace-dev \
libopencv-core-dev libopencv-imgcodecs-dev libopencv-imgproc-dev \
libbz2-dev libpq-dev libproj-dev lua5.3 liblua5.3-dev pandoc \
nlohmann-json3-dev pyosmium
```
Expand All @@ -92,7 +93,7 @@ On a Fedora system, use

```sh
sudo dnf install cmake make gcc-c++ boost-devel expat-devel zlib-devel \
potrace-devel cimg-devel json-devel python3-osmium \
potrace-devel opencv-devel json-devel python3-osmium \
bzip2-devel postgresql-devel proj-devel proj-epsg lua-devel pandoc
```

Expand All @@ -101,7 +102,7 @@ dependencies with:

```sh
sudo yum install cmake make gcc-c++ boost-devel expat-devel zlib-devel \
potrace-devel cimg-devel json-devel python3-osmium \
potrace-devel opencv-devel json-devel python3-osmium \
bzip2-devel postgresql-devel proj-devel proj-epsg lua-devel pandoc
```

Expand Down
72 changes: 48 additions & 24 deletions src/gen/canvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,48 +8,66 @@
*/

#include "canvas.hpp"

#include "raster.hpp"

cimg_library::CImg<int> canvas_t::create_pointlist(geom::point_list_t const &pl,
tile_t const &tile) const
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>

void canvas_t::open_close(unsigned int buffer_size)
{
cimg_library::CImg<int> points{static_cast<unsigned int>(pl.size()), 2};
auto const kernel1 = cv::getStructuringElement(
cv::MORPH_RECT,
cv::Size(static_cast<int>(buffer_size), static_cast<int>(buffer_size)));
auto const kernel2 = cv::getStructuringElement(
cv::MORPH_RECT, cv::Size(static_cast<int>(buffer_size * 2),
static_cast<int>(buffer_size * 2)));

cv::erode(m_rast, m_rast, kernel1);
cv::dilate(m_rast, m_rast, kernel2);
cv::erode(m_rast, m_rast, kernel1);
}

void canvas_t::create_pointlist(std::vector<cv::Point> *out,
geom::point_list_t const &pl,
tile_t const &tile) const
{
out->reserve(pl.size());

int n = 0;
for (auto const point : pl) {
auto const tp = tile.to_tile_coords(point, m_extent);
points(n, 0) = static_cast<int>(static_cast<double>(m_buffer) + tp.x());
points(n, 1) =
static_cast<int>(static_cast<double>(m_buffer + m_extent) - tp.y());
++n;
auto const x = static_cast<double>(m_buffer) + tp.x();
auto const y = static_cast<double>(m_buffer + m_extent) - tp.y();
out->emplace_back(x, y);
}

return points;
}

std::size_t canvas_t::draw_polygon(geom::polygon_t const &polygon,
tile_t const &tile)
{
if (polygon.inners().empty()) {
m_rast.draw_polygon(create_pointlist(polygon.outer(), tile), &White);
return polygon.outer().size();
}

std::size_t num_points = polygon.outer().size();
m_temp.draw_polygon(create_pointlist(polygon.outer(), tile), &White);

std::vector<std::vector<cv::Point>> poly_data;
poly_data.resize(polygon.inners().size() + 1);

create_pointlist(poly_data.data(), polygon.outer(), tile);
std::size_t n = 1;
for (auto const &inner : polygon.inners()) {
num_points += inner.size();
m_temp.draw_polygon(create_pointlist(inner, tile), &Black);
create_pointlist(&poly_data[n], inner, tile);
n++;
}
m_rast |= m_temp;
cv::fillPoly(m_rast, poly_data, cv::Scalar{255});

return num_points;
}

std::size_t canvas_t::draw_linestring(geom::linestring_t const &linestring,
tile_t const &tile)
{
m_rast.draw_line(create_pointlist(linestring, tile), &White);
std::vector<cv::Point> line_data;
create_pointlist(&line_data, linestring, tile);
cv::polylines(m_rast, line_data, false, cv::Scalar{255});
return linestring.size();
}

Expand Down Expand Up @@ -81,13 +99,13 @@ std::size_t canvas_t::draw(geom::geometry_t const &geometry, tile_t const &tile)

void canvas_t::save(std::string const &filename) const
{
m_rast.save(filename.c_str());
cv::imwrite(filename, m_rast);
}

std::string canvas_t::to_wkb(tile_t const &tile, double margin) const
{
std::string wkb;
wkb.reserve(61 + 2 + m_rast.size());
wkb.reserve(61 + 2 + size() * size());

// header
wkb_raster_header header{};
Expand All @@ -106,18 +124,24 @@ std::string canvas_t::to_wkb(tile_t const &tile, double margin) const
add_raster_band(&wkb, band);

// rasterdata
wkb.append(reinterpret_cast<char const *>(m_rast.data()), m_rast.size());
wkb.append(reinterpret_cast<char const *>(begin()),
reinterpret_cast<char const *>(end()));

assert(wkb.size() == 61 + 2 + m_rast.size());
assert(wkb.size() == 61 + 2 + size() * size());

return wkb;
}

void canvas_t::merge(canvas_t const &other) { m_rast |= other.m_rast; }
void canvas_t::merge(canvas_t const &other)
{
cv::bitwise_or(m_rast, other.m_rast, m_rast);
}

std::string to_hex(std::string const &in)
{
std::string result;
result.reserve(in.size() * 2);

char const *const lookup_hex = "0123456789ABCDEF";

for (const auto c : in) {
Expand Down
43 changes: 17 additions & 26 deletions src/gen/canvas.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,48 +13,42 @@
#include "geom.hpp"
#include "tile.hpp"

#define cimg_display 0 // NOLINT(cppcoreguidelines-macro-usage)
#include "CImg.h"
#include <opencv2/core.hpp>

#include <cstddef>

/**
* This class wraps the image class from the CImg library.
* This class wraps the image class from the OpenCV library.
*/
class canvas_t
{
public:
static void info() { cimg_library::cimg::info(); }

/**
* Create a new image canvas. It will be quadratic and have the width and
* height extent + 2*buffer.
*/
canvas_t(std::size_t extent, std::size_t buffer)
: m_extent(extent),
m_buffer(buffer), m_rast{size(), size(), 1, 1, 0}, m_temp{size(), size(),
1, 1, 0}
{}
: m_extent(extent), m_buffer(buffer), m_rast{static_cast<int>(size()),
static_cast<int>(size()),
CV_8UC1, cv::Scalar::all(0)}
{
}

unsigned int size() const noexcept
{
return static_cast<unsigned int>(m_extent + 2 * m_buffer);
}

unsigned char const *begin() const noexcept { return m_rast.begin(); }
unsigned char const *end() const noexcept { return m_rast.end(); }

std::size_t draw(geom::geometry_t const &geometry, tile_t const &tile);
unsigned char const *begin() const noexcept { return m_rast.data; }

unsigned char operator()(int x, int y) const noexcept
unsigned char const *end() const noexcept
{
return m_rast(x, y, 0, 0);
return m_rast.data + (static_cast<size_t>(size() * size()));
}

void open_close(unsigned int buffer_size)
{
m_rast.dilate(buffer_size).erode(buffer_size * 2).dilate(buffer_size);
}
std::size_t draw(geom::geometry_t const &geometry, tile_t const &tile);

void open_close(unsigned int buffer_size);

void save(std::string const &filename) const;

Expand All @@ -63,13 +57,11 @@ class canvas_t
void merge(canvas_t const &other);

private:
constexpr static unsigned char const Black = 0;
constexpr static unsigned char const White = 255;

using image_type = cimg_library::CImg<unsigned char>;
using image_type = cv::Mat;

cimg_library::CImg<int> create_pointlist(geom::point_list_t const &pl,
tile_t const &tile) const;
void create_pointlist(std::vector<cv::Point> *out,
geom::point_list_t const &pl,
tile_t const &tile) const;

std::size_t draw_polygon(geom::polygon_t const &polygon,
tile_t const &tile);
Expand All @@ -80,7 +72,6 @@ class canvas_t
std::size_t m_extent;
std::size_t m_buffer;
image_type m_rast;
image_type m_temp;
}; // class canvas_t

std::string to_hex(std::string const &in);
Expand Down
1 change: 0 additions & 1 deletion src/gen/osm2pgsql-gen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,6 @@ int main(int argc, char *argv[])
break;
case 'V': // --version
log_info("osm2pgsql-gen version {}", get_osm2pgsql_version());
canvas_t::info();
return 0;
case 201: // --log-sql
get_logger().enable_sql();
Expand Down