Giter Site home page Giter Site logo

juliaimages / imagecontrastadjustment.jl Goto Github PK

View Code? Open in Web Editor NEW
11.0 6.0 5.0 17.09 MB

A Julia package for enhancing and manipulating image contrast.

License: MIT License

Julia 100.00%
histogram-equalization gamma-correction normalization contrast-stretching midway-histogram-equalization histogram-matching histogram-specification julia

imagecontrastadjustment.jl's Introduction

ImageContrastAdjustment

A Julia package for enhancing and manipulating image contrast.

Build Status Codecov PkgEval

imagecontrastadjustment.jl's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

imagecontrastadjustment.jl's Issues

Refactor invertible mapping functions?

I've been mentally bikeshedding the linear contrast stretching interface discussed in this thread. I'd planned to just add a few methods to scaleminmax in ImageCore, but I think the functionality fits better in this sub-package.

I think adjust_histogram is a misnomer for the functions within this module that don't involve the construction or adjustment of an image histogram. Looking at scikit-image's exposure module, a distinction is made between histogram-based and non-histogram-based intensity adjustment functions. The same is true for Matlab's image processing toolbox.

With that in mind, I'd like to propose that the non-histogram-based algorithms be moved to a new category AbstractIntensityMappingAlgorithm <: AbstractImageFilter. This would include LinearStretching, ConstrastStretching, GammaCorrection, and other non-binning, invertible maps.

`adjust_histogram` not robust to `NaN`

So I know it's a long stretch but I am working on a project where colored images are badly treated. I sometimes run adjust_histogram(img, Equalization()) and it appears that in transform_density, the input img contains NaN value and an error is returned.
Then the line
index = floor(Int, (val-first_edge)*inv_step_size) + 1 returns an error when isnan(val)

To be honest I don't really know where the NaN values come from.

Generalize `LinearStretching`

There's significant overlap between LinearStretching and a family of related, non-deprecated functions in ImageCore (https://juliaimages.org/latest/function_reference/#ImageCore.scaleminmax, etc.). However, the overlap isn't complete (there's no analogue here for scalesigned(min, center, max), and the APIs don't match, which may become a source of confusion. To reduce the size of the API surface, the missing methods should be added to ImageContrastAdjustment, and the corresponding functions in ImageCore should be deprecated.

To incorporate scalesigned(min, center, max) and scalesigned(maxabs) into LinearStretching, the source -> target intensity mapping can be generalized to accept three (or more) intensity levels, representing a piecewise-linear intensity transformation. Johnny's recent PR #28 is a good base (thanks!), but the function and interface would need to be further overhauled for piecewise-linear maps.

I'd also like to cover the use-case described by @bjarthur in issue #27:

My sole use case is imadjustintensity(img, quantile(img,[0.01,0.99])), which i find quite good at eliminating outliers when adjusting the brightness.

I've typed out the exact same function call countless times in various projects over the last few years. For a more Julian interface, let's look to Percentile. For example,

  • LinearStretching(Percentiles(1, 99))
  • LinearStretching(Quantiles(.015, .985))
  • LinearStretching(Percentiles(0, 50, 100), (-1, 0, 1)) would replace scalesigned(min, center, max)
  • LinearStretching(maxabs, (-1, 0, 1)) would replace scalesigned(maxabs)

Trigger on label event

I'm reading through various benchmark workflows to get some ideas as to how to set up my own.

I think the comment below may no longer be true.

# github action workflow doesn't support action on labels
# this function manually check if PR has label "run benchmarks"

Combining:

I think a label trigger can be achieved with the following YAML adjustments.

on:
  label:
    types: [created, edited]

...

steps:
 - name: Triggered by label
   if: ${{ github.event_name == 'label' && github.event.label.name == 'run benchmark' }}

The label event will only trigger a workflow run if the workflow file is on the master or default branch.

All totally untested of course.

TagBot trigger issue

This issue is used to trigger TagBot; feel free to unsubscribe.

If you haven't already, you should update your TagBot.yml to include issue comment triggers.
Please see this post on Discourse for instructions and more details.

If you'd like for me to do this for you, comment TagBot fix on this issue.
I'll open a PR within a few hours, please be patient!

Is there any Adaptive Linear Stretching algorithms exists and worth adding to the package?

I have recently faced a problem that needs adaptive linear stretching. Basically, the image has different value range at different regions, applying linear stretching globally would not be able to enhance the local contrast.

I assume there should be algorithms similar to the Contrast Limited Adaptive Histogram Equalization that can enhance local contrast. but my naive implementation (split images to regions and apply linear stretching locally) have significant edges artifacts.

if already established methods exists, it would be great help for situation I faced.

LinearStretching() can not do imadjustintensity(..., (minval,maxval))

the args to imadjustintensity specify the "from" range, whereas those of the same name to LinearStretching are the "to" range. are there plans to add this functionality to the new API before the old is deprecated? my sole use case is imadjustintensity(img, quantile(img,[0.01,0.99])), which i find quite good at eliminating outliers when adjusting the brightness.

great to finally get rid of the "im" prefix! thanks for that!

Overflow in ContrastStretching

adjust_histogram(img, ContrastStretching()) is suggested as a deprecation for imstretch; with --depwarn=yes, we get

julia> using Images

julia> img = Gray{N0f8}.([1 0; 0 1])
2×2 Array{Gray{N0f8},2} with eltype Gray{N0f8}:
 Gray{N0f8}(1.0)  Gray{N0f8}(0.0)
 Gray{N0f8}(0.0)  Gray{N0f8}(1.0)

julia> imgs = imstretch(img, 0.3, 0.4)
┌ Warning: `imstretch` will be removed in a future release, please use `adjust_histogram(img, ContrastStretching())` instead.
│   caller = top-level scope at REPL[3]:1
└ @ Core REPL[3]:1
2×2 Array{Gray{Float64},2} with eltype Gray{Float64}:
 Gray{Float64}(0.618123)    Gray{Float64}(0.00274462)
 Gray{Float64}(0.00274462)  Gray{Float64}(0.618123)

(As pointed out in JuliaImages/Images.jl#865 (comment), it would have been nice if this had suggested "please use adjust_histogram(img, ContrastStretching(; t=0.3, slope=0.4)) instead so that it was copy/pastable.)

But if we follow the suggestion, we get:

julia> adjust_histogram(img, ContrastStretching(t=0.3, slope=0.4))
2×2 Array{Gray{N0f8},2} with eltype Gray{N0f8}:
 Gray{N0f8}(0.0)    Gray{N0f8}(0.149)
 Gray{N0f8}(0.149)  Gray{N0f8}(0.0)

which is very different. However:

julia> adjust_histogram(float.(img), ContrastStretching(t=0.3, slope=0.4))
2×2 Array{Gray{Float32},2} with eltype Gray{Float32}:
 Gray{Float32}(0.618123)    Gray{Float32}(0.00274462)
 Gray{Float32}(0.00274462)  Gray{Float32}(0.618123)

indicating that it's overflow at fault.

Specifying the color space for manipulation

(Perhaps, as @johnnychen94 knows,) I am currently rethinking the definition of default color spaces for YIQ and YCbCr in ColorTypes.jl and Colors.jl. (cf. JuliaGraphics/Colors.jl#453, JuliaGraphics/ColorTypes.jl#250)

AFAIK, this is the only package that explicitly uses YIQ. This package is indifferent about the gamma of YIQ color space, even though it is designed to manipulate the contrast. 😅

If the implementation of the conversion from RGB etc. to YIQ is slightly changed, will there be any inconvenience?

In any case, for compatibility and convenience reasons, I think it might be a good idea to allow the user to explicitly specify the color space in which to manipulate the contrast.
So, what about adding the following getter and setter to the keyword arguments of the API?

getluma(c::Colorant)
setluma(c::Colorant, luma::Real)

Also, what about switching the default implementation of the getters and setters depending on the color type?
For example:

color types luma-like value
(fallback) YIQ(c).y
Gray gray(c)
HSV c.v
HSL c.l
HSI c.i
Lab/Luv c.l / 100
XYZ/xyY xyY(c).Y

Of course, the feature should be realized with outside of this package by using MappedArray or something. My main aim is to reduce the impact of breaking changes in ColorTypes.jl and Colors.jl.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.