whyharsha
whyharsha

Reputation: 87

How do I convert some computed values (floating point) to the RGB type in Julia?

I am attempting an image convolution using a 3x3 kernel_test and am running into a challenge with returning the correct type so I can view an image back (after the convolution). My code is as below.

begin
    function update_mat_val(org_clr::AbstractRGB, new_clr::AbstractRGB, n::Number)
        r = reinterpret(N0f8, (red(org_clr) + (red(new_clr) * n)))
        g = reinterpret(N0f8, (green(org_clr) + (green(new_clr) * n)))
        b = reinterpret(N0f8, (blue(org_clr) + (blue(new_clr) * n)))
        
        return RGB(r, g, b)
    end
end
function convolve_image(M::AbstractMatrix, K::AbstractMatrix)
    #M is the matrix, K is the kernel
    
    (m_height, m_width) = size(M)
    (k_height, k_width) = size(K)
    
    conv_mk = zeros(typeof(M[1,1]), m_height+k_height-1, m_width+k_width-1)
    (conv_height, conv_width) = size(conv_mk)
    
    for i in 1:m_height, j in 1:m_width
        for p in 1:k_height, q in 1:k_width
            conv_mk[i+p-1,j+q-1] = update_mat_val(conv_mk[i+p-1,j+q-1], M[i,j], K[p,q])
        end
    end
    
    return conv_mk
end
convolve_image(image, kernel_test)

Initially, I did not use the reinterpret method and the values were falling outside the 0-255 values that the RGB can hold. So after reading up a little online, I tried to use reinterpret. The error before I attempted to reinterpret and after are given in corresponding order below. How do I correctly process the values so I get an image back?

ArgumentError: element type FixedPointNumbers.Normed{UInt8,8} is an 8-bit type representing 256 values from 0.0 to 1.0,

but the values (0.9254901960784314, 0.9686274509803922, 1.0019607843137255) do not lie within this range.

See the READMEs for FixedPointNumbers and ColorTypes for more information.

throw_colorerror_(::Type{FixedPointNumbers.Normed{UInt8,8}}, ::Tuple{Float64,Float64,Float64})@types.jl:686
throw_colorerror(::Type{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8,8}}}, ::Tuple{Float64,Float64,Float64})@types.jl:736
[email protected]:654[inlined]
[email protected]:101[inlined]
[email protected]:87[inlined]
[email protected]:76[inlined]
[email protected]:73[inlined]
[email protected]:849[inlined]
convolve_image(::Array{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8,8}},2}, ::Array{Float64,2})@Other: 12
top-level scope@Local: 1
bitcast: target type not a leaf primitive type

[email protected]:414[inlined]
update_mat_val@Other: 3[inlined]
convolve_image(::Array{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8,8}},2}, ::Array{Float64,2})@Other: 12
top-level scope@Local: 1

Upvotes: 4

Views: 904

Answers (3)

whyharsha
whyharsha

Reputation: 87

This issue keeps recurring with other variants of the code as well. I continue to get errors of the following kind with the code below.

Error Type 1

ArgumentError: element type FixedPointNumbers.Normed{UInt8,8} is an 8-bit type representing 256 values from 0.0 to 1.0,

but the values (0.9602378709470972, 0.992399754308552, 1.018129260997716) do not lie within this range.

Error Type 2

ArgumentError: element type FixedPointNumbers.Normed{UInt8,8} is an 8-bit type representing 256 values from 0.0 to 1.0,

but the values (-0.006372549019607852, -0.0034313725490196026, -0.004411764705882355) do not lie within this range.

Code

function extend_mat(M::AbstractMatrix, i, j)
    (h,w) = size(M)
    return M[clamp(i, 1, h), clamp(j, 1, w)]
end
function convolve(M::AbstractMatrix, K::AbstractMatrix)
    #M is the matrix, K is the kernel
    
    (mh, mw) = size(M)
    (kh, kw) = size(K)
    
    half_kh = kh ÷ 2
    half_kw = kw ÷ 2
    
    conv_mk = similar(M)
    
    @inbounds for i in 1:mh, j in 1:mw
        accumulator = 0 * M[1, 1]
        for p in -half_kh:-half_kh + kh - 1, q in -half_kw:-half_kw + kw - 1
            accumulator += extend_mat(M, i-p, j-q) * K[p,q]
        end
        conv_mk[i, j] = accumulator
    end
    
    return conv_mk
end
function sobel_edge_detect(image, dim = 1)
    sx, sy = Kernel.sobel()
    if dim == 1
        return convolve(image, sx)
    elseif dim == 2
        return convolve(image, sy)
    else
        return convolve(image, sx)
    end
end
sobel_edge_detect(philip)

Upvotes: 0

DNF
DNF

Reputation: 12664

You can write your update function like this

update_mat_val(val1::AbstractRGB, val2::AbstractRGB, n::Number) = val1 + val2 * n

No need for all the conversions all over the place.

Upvotes: 1

whyharsha
whyharsha

Reputation: 87

Update: I managed to figure out the issue.

In particular cases, the convolution results in an r, g or b value > 1.0. That representation cannot work.

My current solution is to limit the convolution to 1.0 (if it exceeds). I am not currently solving for values < 0.0 but that is trivial.

function update_mat_val(org_clr::AbstractRGB, new_clr::AbstractRGB, n::Number)
    r = red(org_clr) + (red(new_clr) * n)
    g = green(org_clr) + (green(new_clr) * n)
    b = blue(org_clr) + (blue(new_clr) * n)
        
    if r > 1.0
        r = 1.0
    end
    
    if g > 1.0
        g = 1.0
    end
    
    if b > 1.0
        b = 1.0
    end
                
    return RGB(r, g, b)
end

Upvotes: 1

Related Questions