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

Image Processing Library Prototype #1450

Merged
merged 41 commits into from
Mar 23, 2021
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
4d78828
doc: add section on enso testing
4e6 Feb 2, 2021
ecbcd65
add: image lib
4e6 Feb 3, 2021
088e534
impl: linear transformation
4e6 Feb 4, 2021
f1d7a8b
impl: vectorized color ops
4e6 Feb 4, 2021
d35d106
impl: vectorized matrix ops
4e6 Feb 6, 2021
d530bcb
feat: add read write flags
4e6 Feb 11, 2021
eb90db3
feat: visualization
4e6 Feb 14, 2021
31a9868
feat: histogram
4e6 Feb 16, 2021
bdde6ea
feat: update Codecs tests
4e6 Feb 24, 2021
31c8371
fix: after rebase
4e6 Mar 15, 2021
0d9746c
feat: bump opencv
4e6 Mar 15, 2021
057be01
test: matrix
4e6 Mar 16, 2021
48baf6d
refactor: remove color
4e6 Mar 17, 2021
390efe3
refactor: move image to standard distrib
4e6 Mar 17, 2021
716b802
doc: std-bits
4e6 Mar 17, 2021
9446132
feat: update histogram
4e6 Mar 17, 2021
e4dce50
feat: image
4e6 Mar 18, 2021
87c29ea
misc: cleanup
4e6 Mar 18, 2021
532fd52
docs: std-lib
4e6 Mar 18, 2021
55246c9
docs: histogram
4e6 Mar 18, 2021
7658945
legel-review
4e6 Mar 18, 2021
d8c5e9d
legel-review: license
4e6 Mar 18, 2021
c513480
legel-review: update licenses
4e6 Mar 18, 2021
5ee1bf9
misc: review comments
4e6 Mar 19, 2021
3c9c08f
refactor: rename eye to identity
4e6 Mar 19, 2021
4ae70e9
feat: convert to RGB
4e6 Mar 19, 2021
d0af36c
feat: test pending without internet
4e6 Mar 19, 2021
32eece6
feat: operations with matrices
4e6 Mar 21, 2021
8ee205b
feat: matrix normalization
4e6 Mar 21, 2021
4dea6b1
feat: handle matrix errors
4e6 Mar 21, 2021
b0cff5e
misc: fixes
4e6 Mar 21, 2021
a1478de
refactor: codecs
4e6 Mar 23, 2021
3be286e
refactor: histogram
4e6 Mar 23, 2021
606d5cc
test: error message
4e6 Mar 23, 2021
9805e2c
doc: arguments
4e6 Mar 23, 2021
92948ee
test: check result
4e6 Mar 23, 2021
e905f95
misc: cleanup
4e6 Mar 23, 2021
d9d8226
refactor: codecs write
4e6 Mar 23, 2021
d9849e5
fix: write
4e6 Mar 23, 2021
9595f24
feat: unstable
4e6 Mar 23, 2021
f4149f5
Merge branch 'main' into wip/db/image-lib
4e6 Mar 23, 2021
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
1 change: 1 addition & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -1254,6 +1254,7 @@ lazy val `std-bits` = project
libraryDependencies ++= Seq(
"com.ibm.icu" % "icu4j" % icuVersion,
"com.univocity" % "univocity-parsers" % "2.9.0",
"org.openpnp" % "opencv" % "4.5.1-0",
"org.xerial" % "sqlite-jdbc" % "3.34.0",
"org.postgresql" % "postgresql" % "42.2.19"
),
Expand Down
5 changes: 5 additions & 0 deletions distribution/std-lib/Standard/THIRD-PARTY/NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ The license information can be found along with the copyright notices.
Copyright notices related to this dependency can be found in the directory `org.checkerframework.checker-qual-3.5.0`.


'opencv', licensed under the BSD License, is distributed with the Standard.
The license file can be found at `licenses/BSD-3-Clause`.
Copyright notices related to this dependency can be found in the directory `org.openpnp.opencv-4.5.1-0`.


'postgresql', licensed under the BSD-2-Clause, is distributed with the Standard.
The license information can be found along with the copyright notices.
Copyright notices related to this dependency can be found in the directory `org.postgresql.postgresql-42.2.19`.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND

1. Redistributions of source code must retain the above copyright notice, this

Copyright (c) 2015, Advanced Micro Devices, Inc.

2. Redistributions in binary form must reproduce the above copyright notice,

IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
41 changes: 39 additions & 2 deletions distribution/std-lib/Standard/src/Base/Data/Vector.enso
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,28 @@ type Vector
arr.set_at i (that.at i-this_len)
Vector arr

## Add `element` to the beginning of `this` vector.

Arguments:
- `element`: An element to add to this vector.

> Example
Add one element in front:
[2, 3].prepend 1 == [1, 2, 3]
prepend : Any -> Vector
prepend element = [element] + this

## Add `element` to the end of `this` vector.

Arguments:
- `element`: An element to add to this vector.

> Example
Add one element to the end:
[1, 2].append 3 == [1, 2, 3]
append : Any -> Vector
append element = this + [element]

## When `this` is a vector of text values, concatenates all the values by
interspersing them with `separator`.

Expand Down Expand Up @@ -373,15 +395,30 @@ type Vector

> Example
To pairwise-sum two vectors:
zip [1, 2, 3] [4, 5, 6] (+) == [5, 7, 9]
[1, 2, 3].zip [4, 5, 6] (+) == [5, 7, 9]
When the `function` is not provided, it defaults to creating a pair
of both elements:
zip [1, 2, 3] [4, 5, 6] == [[1, 4], [2, 5], [3, 6]]
[1, 2, 3].zip [4, 5, 6] == [[1, 4], [2, 5], [3, 6]]
zip : Vector -> (Any -> Any -> Any) -> Vector
zip that function=[_,_] =
len = Math.min this.length that.length
here.new len i-> function (this.at i) (that.at i)

## Extend `this` vector to the length of `n` appending elements `elem` to
the end. If the new length `n` is less than existing length, `this`
vector is returned.

> Example
Extending vector to the length of 5 returns `[1, 2, 3, 0, 0]`
[1, 2, 3].pad 5 0
> Example
Extending vector to the length of 5 returns `[1, 2, 3, 4, 5]`
[1, 2, 3, 4, 5].pad 5 0
pad : Integer -> Any -> Vector
pad n elem =
if this.length >= n then this else
this + (here.fill n-this.length elem)

## Vector to JSON conversion.
to_json : Json.Array
to_json = Json.Array (this.map .to_json)
Expand Down
9 changes: 9 additions & 0 deletions distribution/std-lib/Standard/src/Image.enso
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from Standard.Base import all

import Standard.Image.Codecs
import Standard.Image.Data.Histogram
import Standard.Image.Data.Image

from Standard.Image.Codecs export read, write
from Standard.Image.Data.Histogram export all
from Standard.Image.Data.Image export all
107 changes: 107 additions & 0 deletions distribution/std-lib/Standard/src/Image/Codecs.enso
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
from Standard.Base import all

import Standard.Base.System.File
import Standard.Image.Codecs.Internal
import Standard.Image.Data.Image

polyglot java import org.enso.image.Codecs as Java_Codecs

type Read_Flag

## Read the image with its alpha channel, otherwise the channel gets cropped.
type Read_Alpha_Channel

## Always convert the image to a single channel grayscale image.
type Read_Grayscale

## Use Geographic Data Abstraction Library (GDAL) driver to load images in
geospatial raster data formats.
type Read_Gdal

type Write_Flag

## For a JPEG, this can be a quality from 0 to 100 (the higher, the better).
type Write_Jpeg_Quality value=95

## Enable progressive JPEG compression format. Disabled by default.
type Write_Jpeg_Progressive

## Enable optimized JPEG encoding algorithms. Disabled by default.
type Write_Jpeg_Optimize

## Separate luma quality level, 0 - 100.
type Write_Jpeg_Luma_Quality value=0

## Separate chroma quality level, 0 - 100.
type Write_Jpeg_Chroma_Quality value=0

## For PNG, it can be the compression level from 0 to 9. A higher value
means a smaller size and longer compression time.
type Write_Png_Compression value=3

## For WEBP, this is a quality from 1 to 100 (the higher, the better).
By default (without any parameter) and for quality above 100 the lossless
compression is used.
type Write_Webp_Quality value=101

## Read an image from a file.

The functon reads images in RGB format, or RGBA if the
`Read_Alpha_Channel` flag is specified.

Arguments:
- `location`: the file to read.
- `flags`: the read flags.

> Example
Read the image.
Codecs.read "image.png"

> Example
Read the image with alpha channel.
Codecs.read "image.png" Codecs.Read_Alpha_Channel

> Example
Read the image and convert it to grayscale.
Codecs.read "image.png" Codecs.Read_Grayscale
read : (Text | File) -> (Read_Flag | Vector) -> Image ! File.Io_Error
read location flags=[] =
path = case location of
File.File _ -> location.path
_ -> location
read_flags = case flags of
Vector.Vector _ ->
if flags.is_empty then Java_Codecs.READ_FLAG_EMPTY else
flags.map .to_integer . reduce (_.bit_or _)
_ -> flags.to_integer
Panic.recover (Image.Image (Java_Codecs.read path read_flags)) . catch e->
case e of
Polyglot_Error _ -> Error.throw (File.Io_Error ('Failed to read the file at ' + path + '.'))
err -> Panic.throw err

## Write an image to a file.

> Example
Write the image with applying png compression.
Codecs.write path image

> Example
Write the image with applying png compression.
Codecs.write path image (Codecs.Write_Png_Compression 9)

> Example
Write the image with applying several flags.
Codecs.write path image [Codecs.Write_Jpeg_Quality 40, Codecs.Write_Jpeg_Progressive]
Image.Image.write : (Text | File) -> (Write_Flag | Vector) -> Nothing ! File.Io_Error
Image.Image.write location flags=[] =
path = case location of
File.File _ -> location.path
_ -> location
write_flags = case flags of
Vector.Vector _ -> flags
_ -> [flags]
int_flags = Internal.mat_of_int (write_flags.flat_map x-> [x.to_integer, x.value])
Panic.recover (Java_Codecs.write path this.opencv_mat int_flags) . catch e->
case e of
Polyglot_Error _ -> Panic.throw (File.Io_Error ('Failed to write to the file at ' + path + '.'))
err -> Panic.throw err
47 changes: 47 additions & 0 deletions distribution/std-lib/Standard/src/Image/Codecs/Internal.enso
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from Standard.Base import all

import Standard.Image.Codecs

polyglot java import org.opencv.core.MatOfInt
polyglot java import org.opencv.imgcodecs.Imgcodecs

## PRIVATE
4e6 marked this conversation as resolved.
Show resolved Hide resolved
Codecs.Read_Alpha_Channel.to_integer = Imgcodecs.IMREAD_UNCHANGED

## PRIVATE
Codecs.Read_Grayscale.to_integer = Imgcodecs.IMREAD_GRAYSCALE

## PRIVATE
Codecs.Read_Gdal.to_integer = Imgcodecs.IMREAD_LOAD_GDAL

## PRIVATE
Codecs.Write_Jpeg_Quality.to_integer = Imgcodecs.IMWRITE_JPEG_QUALITY

## PRIVATE
Codecs.Write_Jpeg_Progressive.to_integer = Imgcodecs.IMWRITE_JPEG_PROGRESSIVE

## PRIVATE
Codecs.Write_Jpeg_Progressive.value = 1

## PRIVATE
Codecs.Write_Jpeg_Optimize.to_integer = Imgcodecs.IMWRITE_JPEG_OPTIMIZE

## PRIVATE
Codecs.Write_Jpeg_Optimize.value = 1

## PRIVATE
Codecs.Write_Jpeg_Luma_Quality.to_integer = Imgcodecs.IMWRITE_JPEG_LUMA_QUALITY

## PRIVATE
Codecs.Write_Jpeg_Chroma_Quality.to_integer = Imgcodecs.IMWRITE_JPEG_CHROMA_QUALITY

## PRIVATE
Codecs.Write_Png_Compression.to_integer = Imgcodecs.IMWRITE_PNG_COMPRESSION

## PRIVATE
Codecs.Write_Webp_Quality.to_integer = Imgcodecs.IMWRITE_WEBP_QUALITY

## PRIVATE

Create an OpenCV matrix.
mat_of_int values = MatOfInt.new values.to_array
28 changes: 28 additions & 0 deletions distribution/std-lib/Standard/src/Image/Data/Histogram.enso
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from Standard.Base import all

import Standard.Image.Data.Image

polyglot java import org.enso.image.data.Histogram as Java_Histogram

type Histogram

type Histogram channel data

## Convert histogram data to Json.
to_json : Json
to_json =
bins = Json.from_pairs [["bins", this.data]]
Json.from_pairs [["data", bins]]

## Create a histogram for the specified channel of the image.

Arguments:
`channel`: the channel number.

> Example
Create a histogram.
Image.from_vector [0] . histogram 0
Image.Image.histogram : Integer -> Histogram
Image.Image.histogram channel =
hist = Java_Histogram.calculate this.opencv_mat channel
Histogram channel (Vector.Vector hist.get_data)
Loading