README

Triangle logo

Build Status GoDoc license release homebrew

▲ Triangle is a tool to generate triangulated image using delaunay triangulation. It takes a source image and converts it to an abstract image composed of tiles of triangles.

Sample image

The process
  • First the image is blured out to smothen sharp pixel edges. The more blured an image is the more diffused the generated output will be.
  • Second the resulted image is converted to grayscale mode.
  • Then a sobel filter operator is applied on the grayscaled image to obtain the image edges. An optional threshold value is applied to filter out the representative pixels of the resulted image.
  • Lastly the delaunay algorithm is applied on the pixels obtained from the previous step.
blur = tri.Stackblur(img, uint32(width), uint32(height), uint32(*blurRadius))
gray = tri.Grayscale(blur)
sobel = tri.SobelFilter(gray, float64(*sobelThreshold))
points = tri.GetEdgePoints(sobel, *pointsThreshold, *maxPoints)

triangles = delaunay.Init(width, height).Insert(points).GetTriangles()

Features

Features implemented
  • Can process recursively whole directories and subdirectories concurrently.
  • Supports various image types.
  • There is no need to specify the file type, the CLI tool can recognize automatically the input and output file type.
  • Possibility to save the generated image as an SGV file.
  • The generated SVG file can be accessed from the Web browser directly.
  • Clean and intuitive API. The core method responsible with the image triangulation not only that accepts image files but can also work with image data. This means that the Draw method can be invoked even on data streams. Check this demo for reference.
Features to be implemented
  • Pipe commands

Installation and usage

$ go get -u -f github.com/esimov/triangle/cmd/triangle
$ go install

MacOS (Brew) install

The library can be installed via Homebrew too or by downloading the binary file from the releases folder.

$ brew install triangle
Supported commands
$ triangle --help

The following flags are supported:

Flag Default Description
in n/a Source image
out n/a Destination image
blur 4 Blur radius
pts 2500 Maximum number of points
noise 0 Noise factor
th 20 Points threshold
sobel 10 Sobel filter threshold
solid false Use solid stroke color (yes/no)
wf 0 Wireframe mode (0: without stroke, 1: with stroke, 2: stroke only)
stroke 1 Stroke width
gray false Output in grayscale mode
web false Open the SVG file in the web browser
bg ' ' Background color (specified as hex value)
c system spec. Number of files to process concurrently (workers)
Background color

You can specify a background color in case of transparent background images (.png) by using the -bg flag. This flag accepts a hexadecimal string value. For example setting the flag to -bg=#ffffff00 will set the alpha channel of the resulted image transparent.

Output as image or SVG

By default the output is saved to an image file, but you can export the resulted vertices even to an SVG file. The CLI tool can recognize the output type directly from the file extension. This is a handy addition for those who wish to generate large images without guality loss.

$ triangle -in samples/input.jpg -out output.svg

Using with -web flag you can access the generated svg file directly on the web browser.

$ triangle -in samples/input.jpg -out output.svg -web=true
Supported output types

The following output types are supported: .jpg, .jpeg, .png, .svg.

Process multiple images from a directory concurrently

The CLI tool also let you process multiple images from a directory concurrently. You only need to provide the source and the destination folder by using the -in and -out flags.

$ triangle -in <input_folder> -out <output-folder>
Tweaks

Setting a lower points threshold, the resulted image will be more like a cubic painting. You can even add a noise factor, generating a more artistic, grainy image.

Here are some examples you can experiment with:

$ triangle -in samples/input.jpg -out output.png -wf=0 -pts=3500 -stroke=2 -blur=2
$ triangle -in samples/input.jpg -out output.png -wf=2 -pts=5500 -stroke=1 -blur=10
Examples

Sample_0 Sample_1 Sample_11 Sample_8

License

Copyright © 2018 Endre Simo

This project is under the MIT License. See the LICENSE file for the full license text.

Documentation

Overview

    Package triangle is an image processing library, which converts images to computer generated art using delaunay triangulation.

    The package provides a command line interface, supporting various options for the output customization. Check the supported commands by typing:

    $ triangle --help
    

    Using Go interfaces the API can expose the result either as raster or vector type.

    Example to generate triangulated image and output the result as raster type:

    package main
    
    import (
    	"fmt"
    	"github.com/esimov/triangle"
    )
    
    func main() {
    	p := &triangle.Processor{
    		// Initialize struct variables
    	}
    
    	img := &triangle.Image{*p}
    	_, _, err = img.Draw(file, fq, func() {})
    
    	if err != nil {
    		fmt.Printf("Error on triangulation process: %s", err.Error())
    	}
    }
    

    Example to generate triangulated image and output the result to SVG:

    package main
    
    import (
    	"fmt"
    	"github.com/esimov/triangle"
    )
    
    func main() {
    	p := &triangle.Processor{
    		// Initialize struct variables
    	}
    
    	svg := &triangle.SVG{
    		Title:         "Delaunay image triangulator",
    		Lines:         []triangle.Line{},
    		Description:   "Convert images to computer generated art using delaunay triangulation.",
    		StrokeWidth:   p.StrokeWidth,
    		StrokeLineCap: "round", //butt, round, square
    		Processor:     *p,
    	}
    	_, _, err = svg.Draw(file, fq, func() {
    		// Call the closure function
    	})
    
    	if err != nil {
    		fmt.Printf("Error on triangulation process: %s", err.Error())
    	}
    }
    

    Index

    Constants

    View Source
    const (
    	// WithoutWireframe - generates triangles without stroke
    	WithoutWireframe = iota
    	// WithWireframe - generates triangles with stroke
    	WithWireframe
    	// WireframeOnly - generates triangles only with wireframe
    	WireframeOnly
    )
    View Source
    const PointRate = 0.875

      PointRate defines the default point rate. Changing this value will modify the triangles sizes.

      Variables

      This section is empty.

      Functions

      func Grayscale

      func Grayscale(src *image.NRGBA) *image.NRGBA

        Grayscale converts the image to grayscale mode.

        func Noise

        func Noise(amount int, pxl image.Image, w, h int) *image.NRGBA64

          Noise apply a noise factor, like adobe's grain filter to create a despeckle like image.

          func SobelFilter

          func SobelFilter(img *image.NRGBA, threshold float64) *image.NRGBA

            SobelFilter uses the sobel threshold operator to detect the image edges. See https://en.wikipedia.org/wiki/Sobel_operator

            func StackBlur

            func StackBlur(img *image.NRGBA, radius uint32) *image.NRGBA

              StackBlur applies a blur filter to the provided image. The radius defines the bluring average.

              func ToNRGBA

              func ToNRGBA(img image.Image) *image.NRGBA

                ToNRGBA converts any image type to *image.NRGBA with min-point at (0, 0).

                Types

                type Delaunay

                type Delaunay struct {
                	// contains filtered or unexported fields
                }

                  Delaunay defines the main components for the triangulation.

                  func (*Delaunay) GetTriangles

                  func (d *Delaunay) GetTriangles() []Triangle

                    GetTriangles return the generated triangles.

                    func (*Delaunay) Init

                    func (d *Delaunay) Init(width, height int) *Delaunay

                      Init initialize the delaunay structure.

                      func (*Delaunay) Insert

                      func (d *Delaunay) Insert(points []Point) *Delaunay

                        Insert will insert new triangles into the triangles slice.

                        type Drawer

                        type Drawer interface {
                        	Draw(interface{}, io.Writer) ([]Triangle, []Point, error)
                        }

                          Drawer interface defines the Draw method. This has to be implemented by every struct which declares a Draw method. Using this method the image can be triangulated as raster type or SVG.

                          type Image

                          type Image struct {
                          	Processor
                          }

                            Image extends the Processor struct.

                            func (*Image) Draw

                            func (im *Image) Draw(input interface{}, output interface{}, fn func()) (image.Image, []Triangle, []Point, error)

                              Draw is an interface method which triangulates the source type and outputs the result even to an image or a pixel array. The input could be an image file or a pixel array. This is the reason why interface is used as argument type. It returns the number of triangles generated, the number of points and the error in case exists.

                              type Line

                              type Line struct {
                              	P0          Node
                              	P1          Node
                              	P2          Node
                              	P3          Node
                              	FillColor   color.RGBA
                              	StrokeColor color.RGBA
                              }

                                Line defines the SVG line parameters.

                                type Node

                                type Node struct {
                                	X, Y int
                                }

                                  Node defines a struct having as components the node X and Y coordinate position.

                                  type Point

                                  type Point = image.Point

                                    Point defines a struct having as components the point X and Y coordinate position.

                                    func GetEdgePoints

                                    func GetEdgePoints(img *image.NRGBA, threshold, maxPoints int) []Point

                                      GetEdgePoints retrieves the triangle points after the Sobel threshold has been applied.

                                      type Processor

                                      type Processor struct {
                                      	BlurRadius      int
                                      	SobelThreshold  int
                                      	PointsThreshold int
                                      	MaxPoints       int
                                      	Wireframe       int
                                      	Noise           int
                                      	StrokeWidth     float64
                                      	IsStrokeSolid   bool
                                      	Grayscale       bool
                                      	OutputToSVG     bool
                                      	ShowInBrowser   bool
                                      	BgColor         string
                                      }

                                        Processor type with processing options

                                        type SVG

                                        type SVG struct {
                                        	Width         int
                                        	Height        int
                                        	Title         string
                                        	Lines         []Line
                                        	Color         color.RGBA
                                        	Description   string
                                        	StrokeLineCap string
                                        	StrokeWidth   float64
                                        	Processor
                                        }

                                          SVG extends the Processor struct with the SVG parameters.

                                          func (*SVG) Draw

                                          func (svg *SVG) Draw(input io.Reader, output io.Writer, fn func()) (image.Image, []Triangle, []Point, error)

                                            Draw triangulate the source image and output the result to an SVG file. It returns the number of triangles generated, the number of points and the error in case exists.

                                            type Triangle

                                            type Triangle struct {
                                            	Nodes []Node
                                            	// contains filtered or unexported fields
                                            }

                                              Triangle struct defines the basic components of a triangle. It's constructed by nodes, it's edges and the circumcircle which describes the triangle circumference.

                                              Directories

                                              Path Synopsis
                                              cmd