Programming


neural-style-tf: Another open source alternative to Prisma (for advanced users) 1

Recently we stumbled upon another very interesting project, it is called neural-style-tf which is a TensorFlow implementation of an artificial system based on Convolutional neural networks and attempts to separate and combine the content of one image with the style of another.

According to the authors, this tool is based on the following papers

What this tool does is ‘simple’, it takes as input two images, the style image and the content image and using the style image, it tries to recreate the content image in such way that the content image looks like it was created using the same technique as the style image.
Following, is an example of a photograph that was recreated using the style of The Starry Night.

This tool offers a ton of possibilities and options, which we still did not play through yet.
Overall, we are very happy with the initial results we got. The final renderings look really nice and the fact that you get to choose your own style images it gives this tool a very nice advantage.

What we did not like though, is that it takes a lot of time and memory to complete the rendering of a single image (especially if you do not use a GPU to speed up the process).
This issue with the resources is normal and expected, unfortunately though it limits the fun out of the system. Each experiment you make is blocking you for some time and you cannot fiddle with the results in real time.

We installed this tool on an Ubuntu GNU/Linux with success.
Following are the exact commands we used to install it on Ubuntu and convert our first image (the one above).

cd ~;
sudo apt-get install python-pip python-dev;
pip install tensorflow;
pip install tensorflow-gpu;
pip install scipy;
git clone https://github.com/opencv/opencv.git;
cd ~/opencv;
mkdir release;
cd release;
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..;
make;
sudo make install;
cd ~;
git clone https://github.com/cysmith/neural-style-tf.git;
cd neural-style-tf/;
wget http://www.vlfeat.org/matconvnet/models/imagenet-vgg-verydeep-19.mat;
#After everything is complete, it is time to create our first 'artistic' image.
python neural_style.py --content_img "/home/bytefreaks/Pictures/Aphrodite Hills Golf Course - Paphos, Cyprus.jpg" --style_imgs "/home/bytefreaks/Pictures/Van_Gogh_-_Starry_Night_-_Google_Art_Project.jpg" --max_size 1250 --max_iterations 1500 --device /cpu:0 --verbose;

Following are the exact commands we used to install it on CentOS 7 (64bit) and convert our first image (the one above).


cd ~;
sudo yum install python-pip cmake;
sudo pip install --upgrade pip;
sudo pip install tensorflow scipy numpy;
git clone https://github.com/opencv/opencv.git;
cd ~/opencv;
mkdir release;
cd release;
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..;
make;
sudo make install;
cd ~;
git clone https://github.com/cysmith/neural-style-tf.git;
cd neural-style-tf/;
wget http://www.vlfeat.org/matconvnet/models/imagenet-vgg-verydeep-19.mat;
export PYTHONPATH=$PYTHONPATH:/usr/local/lib/python2.7/site-packages
python neural_style.py --content_img "/home/bytefreaks/Pictures/Aphrodite Hills Golf Course - Paphos, Cyprus.jpg" --style_imgs "/home/bytefreaks/Pictures/Van_Gogh_-_Starry_Night_-_Google_Art_Project.jpg" --max_size 1250 --max_iterations 1500 --device /cpu:0 --verbose;

Our input images were the following:

Content Image

Style Image

Useful links


C/C++: Full example of reading a whole binary file to buffer 1

The following example will read a binary in full and store it to a buffer in memory.

[download id=”2487″]

We used the custom structure binary_data_t to store the data information.
This structure stores the pointer to the data and their size.

struct binary_data_t {
  long size;
  void *data;
};

In main.cpp we performed three tests

  1. Reading a file that exists and is not empty
  2. Reading a non-existing file
  3. Reading an empty file

[download id=”2487″]

file_helpers.h


#ifndef GM_S_LITTLE_HELPERS_FILE_HELPERS_H
#define GM_S_LITTLE_HELPERS_FILE_HELPERS_H

#ifdef __cplusplus
extern "C" {
#endif

typedef struct binary_data_t binary_data_t;
struct binary_data_t {
  long size;
  void *data;
};

binary_data_t * read_file(const char *filename);

#ifdef __cplusplus
}
#endif

#endif //GM_S_LITTLE_HELPERS_FILE_HELPERS_H

file_helpers.c


#include <stdio.h>
#include <malloc.h>
#include "file_helpers.h"


//Returns a binary_data_t structure if reading the file was OK.
//In case of an error it always returns NULL.
binary_data_t *read_file(const char *filename) {

  //Allocated our binary data structure
  binary_data_t *binary_data = malloc(sizeof(binary_data_t));
  if (binary_data != NULL) {

    binary_data->size = 0;
    void *buffer = NULL;
    long position;
    //Open the file for reading in binary mode
    FILE *fIn = fopen(filename, "rb");

    if (fIn != NULL) {
      //Go to the end of the file
      const int fseek_end_value = fseek(fIn, 0, SEEK_END);
      if (fseek_end_value != -1) {

        //Get the current position in the file (in bytes)
        position = ftell(fIn);
        if (position != -1) {

          //Go back to the beginning of the file
          const int fseek_set_value = fseek(fIn, 0, SEEK_SET);
          if (fseek_set_value != -1) {

            //Allocate enough space to read the whole file
            buffer = malloc(position);
            if (buffer != NULL) {

              //Read the whole file to buffer
              const long size = fread(buffer, 1, position, fIn);

              if (size == position) {
                binary_data->size = position;
                binary_data->data = buffer;

                fclose(fIn);
                return binary_data;
              }
              free(buffer);
            }
          }
        }
      }
      fclose(fIn);
    }
    free(binary_data);
  }
  return NULL;
}

main.cpp


#include <iostream>
#include "file_helpers.h"

int main(int argc, char *argv[]) {

  //Testing a non-zero sized file
  //read_file() will return a binary_data_t where size will be non zero
  binary_data_t *binary_data_non_zero = read_file(argv[0]);
  //Testing for a non-existing file
  //read_file() will return a NULL pointer
  binary_data_t *binary_data_not_existing = read_file("some file that does not exist...");
  const char * filename = "/tmp/some_empty_file";
  //Creating an empty file
  FILE * fout = fopen(filename, "w");
  fclose(fout);
  //Testing for an empty file
  //read_file() will return a binary_data_t where size will be zero
  binary_data_t *binary_data_empty = read_file(filename);

  return EXIT_SUCCESS;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.6)
project(GM_s_Little_Helpers)

set(CMAKE_CXX_STANDARD 11)

include_directories(${CMAKE_CURRENT_SOURCE_DIR})

set(SOURCE_FILES main.cpp file_helpers.c file_helpers.h)
add_executable(GM_s_Little_Helpers ${SOURCE_FILES})

target_link_libraries(GM_s_Little_Helpers)

[download id=”2487″]


asn1c: Full working example of ASN.1 in C/C++

The following project demonstrates a full working example of encoding and decoding ASN.1 structures using the asn1c compiler of http://lionet.info/asn1c/

In this project we assumed that we have to encode a set of geometric elements, including:

  • A rectangle that is composed by its height and its width
  • A rectangular cuboid that it is composed by a rectangle and a depth parameter
  • A list of rectangular cuboids that has no limit on how many elements to add to it
  • A list of rectangular cuboids that must have at least one element and at most three
  • We assume that all parameters should be positive integer values

[download id=”2470″]

Following is our ASN.1 syntax to describe the above elements:

Geometry.asn1

GeometryModule DEFINITIONS ::= BEGIN

Rectangle ::= SEQUENCE {
    height INTEGER (0..MAX),
    width INTEGER (0..MAX)
}

RectangularCuboid ::= SEQUENCE {
    depth INTEGER (0..MAX),
    rectangle Rectangle
}

UnlimitedRectangularCuboids ::= SEQUENCE OF RectangularCuboid

LimitedRectangularCuboids ::= SEQUENCE SIZE(1..3) OF RectangularCuboid

END

Inside the directory where our source is located, we created folder called geometryASN.
From that folder we executed the following command to generate the c code that is needed for our C/C++ source code to operate:

asn1c -fcompound-names -gen-PER ../Geometry.asn1

Following is our C source code that creates new ANS.1 elements, encodes them, decodes them and verifies that all limitations and constraints were met.

[download id=”2470″]

main.cpp


//From the folder geometryASN, to convert the ASN1 to c execute the following
// asn1c -fcompound-names -gen-PER ../Geometry.asn1
#include <iostream>
#include "geometryASN/Rectangle.h"
#include "geometryASN/RectangularCuboid.h"
#include "geometryASN/LimitedRectangularCuboids.h"
#include "geometryASN/UnlimitedRectangularCuboids.h"

bool validate_constraints(asn_TYPE_descriptor_t *type_descriptor, const void *struct_ptr) {

  char error_buffer[128];
  size_t error_length = sizeof(error_buffer);
  const int return_value = asn_check_constraints(type_descriptor, struct_ptr, error_buffer, &error_length);

  if (return_value) {
    perror("asn_check_constraints() failed");
  }
  return (return_value == 0);
}

void *encode_and_decode_object(asn_TYPE_descriptor_t *type_descriptor, void *struct_ptr) {

  //First we validate that our object meets the expected constraints
  if (validate_constraints(type_descriptor, struct_ptr)) {
    void *buffer;
    asn_per_constraints_s *constraints = NULL;
    //Then, we encode the object to ASN.1 and assign the data to a buffer in memory
    const ssize_t ec = uper_encode_to_new_buffer(type_descriptor, constraints, struct_ptr, &buffer);
    if (ec == -1) {
      perror("uper_encode_to_new_buffer() failed");
    } else {
      //ASN.1 encoded object is not in the buffer variable and it is available for you to use.
      //Finally, since the encoding process went fine, we decode the data to verify with our own eyes that the process went smoothly
      void *decoded_object = 0;
      const asn_dec_rval_t rval = uper_decode(0, type_descriptor, &decoded_object, buffer, (size_t) ec, 0, 0);
      free(buffer);
      if (rval.code != RC_OK) {
        perror("uper_decode() failed");
        fprintf(stderr, "Broken encoding at byte %ld\n", rval.consumed);
      } else {
        return decoded_object;
      }
    }
  }
  return NULL;
}

int main(int argc, char *argv[]) {

  //Scenario A: We test basic encoding and decoding on a Rectangle.
  {
    //First we create a rectangle and then we encode it
    Rectangle_t *rectangle = (Rectangle_t *) calloc(1, sizeof(Rectangle_t));
    if (rectangle == NULL) {
      perror("calloc() failed");
      exit(EXIT_FAILURE);
    }
    rectangle->height = 10;
    rectangle->width = 150;

    Rectangle_t *decoded_rectangle = (Rectangle_t *) encode_and_decode_object(&asn_DEF_Rectangle, rectangle);

    if (decoded_rectangle != NULL) {
      if (rectangle->height != decoded_rectangle->height || rectangle->width != decoded_rectangle->width) {
        perror("uper_decode() failed. Wrong values found after decoding");
        ASN_STRUCT_FREE(asn_DEF_Rectangle, rectangle);
        ASN_STRUCT_FREE(asn_DEF_Rectangle, decoded_rectangle);
        exit(EXIT_FAILURE);
      }
    }
    ASN_STRUCT_FREE(asn_DEF_Rectangle, rectangle);
    ASN_STRUCT_FREE(asn_DEF_Rectangle, decoded_rectangle);
  }

  //Scenario B: We test basic encoding and decoding on a Rectangle.
  //We will provide a value that is out of the constraints area to force the test to fail.
  {
    //First we create a rectangle and then we encode it
    Rectangle_t *rectangle = (Rectangle_t *) calloc(1, sizeof(Rectangle_t));
    if (rectangle == NULL) {
      perror("calloc() failed");
      exit(EXIT_FAILURE);
    }
    rectangle->height = -10;
    rectangle->width = 150;

    Rectangle_t *decoded_rectangle = (Rectangle_t *) encode_and_decode_object(&asn_DEF_Rectangle, rectangle);

    if (decoded_rectangle != NULL) {
      perror("This test should have failed due to the constaint on the range of the valid values.");
      ASN_STRUCT_FREE(asn_DEF_Rectangle, rectangle);
      ASN_STRUCT_FREE(asn_DEF_Rectangle, decoded_rectangle);
      exit(EXIT_FAILURE);
    }
    ASN_STRUCT_FREE(asn_DEF_Rectangle, rectangle);
  }

  //Scenario C: We test basic encoding and decoding on a Rectangular Cuboid.
  {
    //First we create a rectangular cuboid and then we encode it
    RectangularCuboid_t *rectangular_cuboid = (RectangularCuboid_t *) calloc(1, sizeof(RectangularCuboid_t));
    if (rectangular_cuboid == NULL) {
      perror("calloc() failed");
      exit(EXIT_FAILURE);
    }
    rectangular_cuboid->depth = 27;
    rectangular_cuboid->rectangle.height = 10;
    rectangular_cuboid->rectangle.width = 150;

    RectangularCuboid_t *decoded_rectangular_cuboid = (RectangularCuboid_t *) encode_and_decode_object(
        &asn_DEF_RectangularCuboid, rectangular_cuboid);

    if (decoded_rectangular_cuboid != NULL) {
      if (rectangular_cuboid->rectangle.height != decoded_rectangular_cuboid->rectangle.height
          || rectangular_cuboid->rectangle.width != decoded_rectangular_cuboid->rectangle.width
          || rectangular_cuboid->depth != decoded_rectangular_cuboid->depth) {
        perror("uper_decode() failed. Wrong values found after decoding");
        ASN_STRUCT_FREE(asn_DEF_RectangularCuboid, rectangular_cuboid);
        ASN_STRUCT_FREE(asn_DEF_RectangularCuboid, decoded_rectangular_cuboid);
        exit(EXIT_FAILURE);
      }
    }
    ASN_STRUCT_FREE(asn_DEF_RectangularCuboid, rectangular_cuboid);
    ASN_STRUCT_FREE(asn_DEF_RectangularCuboid, decoded_rectangular_cuboid);
  }

  //Scenario D: We will create an array of elements that has no limitation on its size.
  {
    UnlimitedRectangularCuboids_t *unlimited_rectangular_cuboids = (UnlimitedRectangularCuboids_t *) calloc(1,
                                                                                                            sizeof(UnlimitedRectangularCuboids_t));
    if (unlimited_rectangular_cuboids == NULL) {
      perror("calloc() failed");
      exit(EXIT_FAILURE);
    }

    int i;
    for (i = 0; i < 10; i++) {       RectangularCuboid_t *tmp_rectangular_cuboid = (RectangularCuboid_t *) calloc(1, sizeof(RectangularCuboid_t));       if (tmp_rectangular_cuboid == NULL) {         perror("calloc() failed");         exit(EXIT_FAILURE);       }       tmp_rectangular_cuboid->depth = i;
      tmp_rectangular_cuboid->rectangle.height = i * 11;
      tmp_rectangular_cuboid->rectangle.width = i * 101;

      const int result = asn_set_add(unlimited_rectangular_cuboids, tmp_rectangular_cuboid);
      if (result != 0) {
        perror("asn_set_add() failed");
        ASN_STRUCT_FREE(asn_DEF_UnlimitedRectangularCuboids, unlimited_rectangular_cuboids);
        exit(EXIT_FAILURE);
      }
    }

    UnlimitedRectangularCuboids_t *decoded_unlimited_rectangular_cuboids = (UnlimitedRectangularCuboids_t *) encode_and_decode_object(
        &asn_DEF_UnlimitedRectangularCuboids, unlimited_rectangular_cuboids);

    if (decoded_unlimited_rectangular_cuboids != NULL) {
      for (i = 0; i < decoded_unlimited_rectangular_cuboids->list.count; i++) {
        RectangularCuboid_t *tmp_rectangular_cuboid = decoded_unlimited_rectangular_cuboids->list.array[i];
        if (tmp_rectangular_cuboid->rectangle.height != i * 11
            || tmp_rectangular_cuboid->rectangle.width != i * 101
            || tmp_rectangular_cuboid->depth != i) {
          perror("uper_decode() failed. Wrong values found after decoding");
          ASN_STRUCT_FREE(asn_DEF_UnlimitedRectangularCuboids, unlimited_rectangular_cuboids);
          ASN_STRUCT_FREE(asn_DEF_UnlimitedRectangularCuboids, decoded_unlimited_rectangular_cuboids);
          exit(EXIT_FAILURE);
        }
      }
    }
    ASN_STRUCT_FREE(asn_DEF_UnlimitedRectangularCuboids, unlimited_rectangular_cuboids);
    ASN_STRUCT_FREE(asn_DEF_UnlimitedRectangularCuboids, decoded_unlimited_rectangular_cuboids);
  }

  //Scenario E: We will create an array of elements that has a limitation on how many elements it can accept.
  //We will add more elements than expected and we expect the encoding to fail.
  {
    LimitedRectangularCuboids_t *limited_rectangular_cuboids = (LimitedRectangularCuboids_t *) calloc(1,
                                                                                                      sizeof(LimitedRectangularCuboids_t));
    if (limited_rectangular_cuboids == NULL) {
      perror("calloc() failed");
      exit(EXIT_FAILURE);
    }

    int i;
    for (i = 0; i < 10; i++) {       RectangularCuboid_t *tmp_rectangular_cuboid = (RectangularCuboid_t *) calloc(1, sizeof(RectangularCuboid_t));       if (tmp_rectangular_cuboid == NULL) {         perror("calloc() failed");         exit(EXIT_FAILURE);       }       tmp_rectangular_cuboid->depth = i;
      tmp_rectangular_cuboid->rectangle.height = i * 11;
      tmp_rectangular_cuboid->rectangle.width = i * 101;

      const int result = asn_set_add(limited_rectangular_cuboids, tmp_rectangular_cuboid);
      if (result != 0) {
        perror("asn_set_add() failed");
        ASN_STRUCT_FREE(asn_DEF_LimitedRectangularCuboids, limited_rectangular_cuboids);
        exit(EXIT_FAILURE);
      }
    }

    LimitedRectangularCuboids_t *decoded_limited_rectangular_cuboids = (LimitedRectangularCuboids_t *) encode_and_decode_object(
        &asn_DEF_LimitedRectangularCuboids, limited_rectangular_cuboids);

    if (decoded_limited_rectangular_cuboids != NULL) {
      perror("This test should have failed due to limitation on the size of the list.");
      ASN_STRUCT_FREE(asn_DEF_LimitedRectangularCuboids, limited_rectangular_cuboids);
      ASN_STRUCT_FREE(asn_DEF_LimitedRectangularCuboids, decoded_limited_rectangular_cuboids);
      exit(EXIT_FAILURE);
    }
    ASN_STRUCT_FREE(asn_DEF_LimitedRectangularCuboids, limited_rectangular_cuboids);
  }

  printf ("All tests were successful\n");
  return EXIT_SUCCESS;
}

[download id=”2470″]


C/C++: Full example using a linked list with custom struct

The following code is an example that presents some basic functionality on simply linked lists. Specifically, it presents how to add an element to an empty list and then how to add more elements either to the start (prepend) or to the end (append) of the list.

[download id=”2444″]

We assume that our structure holds an integer and a dynamically created string, which we free after pop.

[download id=”2444″]

 

Source file (list_helpers.c)

#include <malloc.h>
#include "list_helpers.h"

void append(node_t **head, element_t *element) {

  struct node_t *new = malloc(sizeof(node_t));
  new->element = element;
  new->next = NULL;

  if (*head == NULL) {
    *head = new;
    return;
  }

  struct node_t *current = *head;

  while (current->next != NULL) {
    current = current->next;
  }

  current->next = new;
  return;
}

void prepend(node_t **head, element_t *element) {
  struct node_t *new = malloc(sizeof(node_t));

  new->element = element;
  new->next = *head;
  *head = new;
}

element_t *pop(node_t **head) {

  node_t *next = NULL;

  if (*head == NULL) {
    return NULL;
  }

  next = (*head)->next;
  element_t *element = (*head)->element;
  free(*head);
  *head = next;

  return element;
}

void clear(node_t **head) {
  element_t *current = pop(head);
  while (current != NULL) {
    free(current->username);
    free(current);
    current = pop(head);
  }
}

Header file (list_helpers.h)

#ifndef GM_S_LITTLE_HELPERS_LIST_HELPERS_H
#define GM_S_LITTLE_HELPERS_LIST_HELPERS_H

#ifdef __cplusplus
extern "C" {
#endif

typedef struct element_t element_t;
struct element_t {
  //We add random members to the element struct for the sake of the example
  char *username;
  unsigned int server;
};

typedef struct node_t node_t;
struct node_t {
  element_t *element;
  node_t *next;
};

void append(node_t **head, element_t *element);

void prepend(node_t **head, element_t *element);

element_t *pop(node_t **head);

void clear(node_t **head);

#ifdef __cplusplus
}
#endif

#endif //GM_S_LITTLE_HELPERS_LIST_HELPERS_H

Usage example (main.cpp)

#include <iostream>
#include "list_helpers.h"

element_t *create_user(const unsigned int server, const char *username) {

  element_t *user = (element_t *) malloc(sizeof(element_t));
  user->server = server;

  //For the sake of the example we used snprintf.
  //Upon successful return, snprintf returns the number of characters printed (excluding the null byte used to end output to strings).
  //For that reason we add one at the end of the length.
  const int length = snprintf(NULL, 0, "%s", username) + 1;
  user->username = (char *) malloc((sizeof(char) * length));
  snprintf(user->username, (size_t) length, "%s", username);
  return user;
}

int main(int argc, char *argv[]) {

  node_t *head = NULL;

  //Add the first element to the linked list
  append(&head, create_user(10, "xeirwn"));

  //Add the second element to the end of the linked list
  append(&head, create_user(12, "test"));

  //Add the third element to the end of the linked list
  append(&head, create_user(14, "banana"));

  //Add the fourth element to the beginning of the linked list
  prepend(&head, create_user(8, "apple"));

  //Popping each one to process it and then free it
  //Clearing the list
  element_t *current = pop(&head);
  while (current != NULL) {

    printf("%s\t%u\n", current->username, current->server);
    free(current->username);
    free(current);
    current = pop(&head);
  }

  //Safely clear the list. In this specific scenario it will have 0 side effects as the list was cleared above
  clear(&head);
  return 0;
}

[download id=”2444″]