Automatic Threshold image

How can I do the process …

This is my code.
I’m working in Juno.

using ImageContrastAdjustment, Images, ImageFiltering, TestImages, ColorTypes, HistogramThresholding
const ICA = ImageContrastAdjustment

function example()
img = testimage(“circulo”)

# Grayscale image.
imgg = Gray.(img)

# Linear contrast stretching.
imggₗ = ICA.adjust_histogram(ICA.LinearStretching(), imgg)

# Histogram Equalization.
imggₑ = ICA.adjust_histogram(ICA.Equalization(), imgg)

#=
   admiminsion and subtracion
 =#
R₁ = float.(imggₗ) + float.(imggₑ)

R₂ = R₁ - float.(imggₑ)

#  imggₗ + imggₗ + imggₑ.
R₃ = R₁ + R₂

# Applying a minimum filter.
window_size = (-1:1, -1:1)
imgmin = mapwindow(minimum, R₃, window_size)

# divide el intervalo del valor más pequeño al más grande en imgmin en 256 bin
edges, counts = ICA.build_histogram(imgmin, 256, minval = minimum(imgmin), maxval = maximum(imgmin))

#=
La matriz `count` almacena en el índice 0 las frecuencias que estaban por debajo de
  primer borde del cubo. Ya que estamos buscando un umbral sobre el intervalo
  divididos por `edges` necesitamos descartar la primera bandeja en` count`
  de modo que las dimensiones de `edge` y` count` coincidan.
=#
t = find_threshold(Otsu(), counts[1:end], edges)

# Aplica el umbral a imgmin y checo el resultado.
img₀₁ = zeros(Gray{Bool}, axes(imgmin))
for i in CartesianIndices(img)
    img₀₁[i] = imgmin[i] < t ? 0 : 1
end
display(img₀₁)

end

example()

as a result I get this

I need the white part to turn black and the black part to turn white.

this is my original image…

Possibly exchange the 0 and the 1 in

for i in CartesianIndices(img)
    img₀₁[i] = imgmin[i] < t ? 0 : 1
end

Or just use

for i in CartesianIndices(img)
    img₀₁[i] = imgmin[i] < t
end

How about imgmin .< t or .!(imgmin .< t) alt. imgmin .≮ t to invert

1 Like

How could you define the range in admission and subtraction over an image?

enter (0-255) without going past 255 or reducing me from 0.

my code is something like this …

#=
admiminsion and subtracion
=#
R₁ = float.(imggₗ) + float.(imggₑ)

R₂ = R₁ - float.(imggₑ)

#  imggₗ + imggₗ + imggₑ.
R₃ = R₁ + R₂

but there the error is that I’m taking float values …

how could I do it to establish the range (0-255).

help me…!

clamp

if … without using float … because with float it is an error to the procedure, and so with float you can not enter whole values to put the range (0-255).

and how do I use clamp

this correct

#=
   admiminsion and subtracion
 =#
R₁ = clamp(0,255).(imggₗ) + clamp(0,255).(imggₑ)

R₂ = R₁ - clamp(0,255).(imggₑ)

#  imggₗ + imggₗ + imggₑ.
R₃ = R₁ + R₂

clamp does not know how work directly on the image pixel type you use.
You would have to overload clamp or translate to a numeric array, clamp that, and translate back to an image array. Note that clamping to 0…255 may mean clamping values 0.0…1.0 or some other range depending upon the representation of your image’s colorant/greyscale.

this is the online help for clamp

help?> clamp
search: clamp clamp!

  clamp(x, lo, hi)

  Return x if lo <= x <= hi. If x > hi, return hi. If x < lo, return lo. Arguments are promoted to a common
  type.

  Examples
  ≡≡≡≡≡≡≡≡≡≡

  julia> clamp.([pi, 1.0, big(10.)], 2., 9.)
  3-element Array{BigFloat,1}:
   3.141592653589793238462643383279502884197169399375105820974944592307816406286198
   2.0
   9.0

  julia> clamp.([11,8,5],10,6) # an example where lo > hi
  3-element Array{Int64,1}:
    6
    6
   10
1 Like

and how can I use cleap in my code … using the range (0-255) without overflowing.

Also

you can just write

stretch = ICA.adjust_histogram(ICA.LinearStretching(), imgg)
adjust  =  ICA.adjust_histogram(ICA.Equalization(), imgg)
r3 = 2*stretch + adjust

This works.

using Images, ImageView, ImageContrastAdjustment, HistogramThresholding, TestImages

const ICA = ImageContrastAdjustment

img = testimage("lake_color") # change this to the image file you are using

# Grayscale image.
imgg = Gray.(img)

# Linear contrast stretching.
imggₗ = ICA.adjust_histogram(ICA.LinearStretching(), imgg)

# Histogram Equalization.
imggₑ = ICA.adjust_histogram(ICA.Equalization(), imgg)

#=
   admiminsion and subtracion
=#
R₃ = imggₗ + imggₗ + imggₑ

# Applying a minimum filter
window_size = (-1:1, -1:1)
imgmin = mapwindow(minimum, R₃, window_size)

# divide el intervalo del valor más pequeño al más grande en imgmin en 256 bin
edges, counts = ICA.build_histogram(imgmin, 256, 
                     minval = minimum(imgmin), maxval = maximum(imgmin))

#=
La matriz `count` almacena en el índice 0 las frecuencias que estaban por debajo de
  primer borde del cubo. Ya que estamos buscando un umbral sobre el intervalo
  divididos por `edges` necesitamos descartar la primera bandeja en` count`
  de modo que las dimensiones de `edge` y` count` coincidan.
=#
t = find_threshold(Otsu(), counts[1:end], edges)

# Aplica el umbral a imgmin y checo el resultado.
img₀₁ = zeros(Gray{Bool}, axes(imgmin))
for i in CartesianIndices(img)
   img₀₁[i] = imgmin[i] < t
end

imshow(img₀₁)

you can put it in a function

using Images, ImageView, ImageContrastAdjustment, HistogramThresholding, TestImages

const ICA = ImageContrastAdjustment

function example()
	img = testimage("lake_color") # change this to the image file you are using

	# Grayscale image.
	imgg = Gray.(img)

	# Linear contrast stretching.
	imggₗ = ICA.adjust_histogram(ICA.LinearStretching(), imgg)

	# Histogram Equalization.
	imggₑ = ICA.adjust_histogram(ICA.Equalization(), imgg)

	#=
	   admiminsion and subtracion
	=#
	R₃ = imggₗ + imggₗ + imggₑ

	# Applying a minimum filter
	window_size = (-1:1, -1:1)
	imgmin = mapwindow(minimum, R₃, window_size)

	# divide el intervalo del valor más pequeño al más grande en imgmin en 256 bin
	edges, counts = ICA.build_histogram(imgmin, 256, 
	                     minval = minimum(imgmin), maxval = maximum(imgmin))

	#=
	La matriz `count` almacena en el índice 0 las frecuencias que estaban por debajo de
	  primer borde del cubo. Ya que estamos buscando un umbral sobre el intervalo
	  divididos por `edges` necesitamos descartar la primera bandeja en` count`
	  de modo que las dimensiones de `edge` y` count` coincidan.
	=#
	t = find_threshold(Otsu(), counts[1:end], edges)

	# Aplica el umbral a imgmin y checo el resultado.
	img₀₁ = zeros(Gray{Bool}, axes(imgmin))
	for i in CartesianIndices(img)
	   img₀₁[i] = imgmin[i] < t
	end

	imshow(img₀₁)
end

example()

Sorry friend, a question …

(Maybe it sounds silly)

and where are you establishing the range between (0-255) of the process?

Why do you think that the Gray pixel values can be outside of that range?

julia> typeof(R₃)
Array{Gray{Normed{UInt8,8}},2}

The UInt8 there means that, internally, pixel values can range from typemin(UInt8) to typemax(UInt8)

julia> Int(typemin(UInt8)), Int(typemax(UInt8))
(0, 255)

The Normed means the values are normalized floats in the range [0.0, 1.0].
Maybe you have some unusual image format or you use some other Grayer or the the image may have been tampered. You can force the matter this way

function clampgray(im::AbstractArray)
    gray = Gray.(im)
    T = typeof(gray)
    gray = T(map(x->clamp(x, 0.0, 1.0), gray))
    return gray
end
   
# and replace 
# imgg = Gray.(img)
# with
imgg = clampgray(img)

if you are really concerned … or just want to see 255 (UInt(255) == 0xff):

clampgraypixel(pixel) =
    N0f8(clamp(x.val.i, 0x00, 0xff) / 0xff)
    
function clampgray(im::AbstractArray)
    gray = Gray.(im)
    T = typeof(gray)
    gray = T(map(pixel->clampgraypixel(pixel), imgg)))
    return gray
end