Image processing 如何将一些计算值(浮点)转换为Julia中的RGB类型?

Image processing 如何将一些计算值(浮点)转换为Julia中的RGB类型?,image-processing,colors,casting,julia,Image Processing,Colors,Casting,Julia,我正在尝试使用3x3 kernel_测试进行图像卷积,但遇到了返回正确类型的挑战,因此我可以查看图像(卷积后)。我的代码如下 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, (

我正在尝试使用3x3 kernel_测试进行图像卷积,但遇到了返回正确类型的挑战,因此我可以查看图像(卷积后)。我的代码如下

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
最初,我没有使用重新解释方法,并且这些值超出了RGB可以容纳的0-255个值。所以在网上读了一点之后,我试着使用reinterpret。我尝试重新解释之前和之后的错误在下面的相应顺序中给出。如何正确处理这些值,以便恢复图像

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
checkval@types.jl:654[inlined]
RGB@types.jl:101[inlined]
_convert@conversions.jl:87[inlined]
cconvert@conversions.jl:76[inlined]
convert@conversions.jl:73[inlined]
setindex!@array.jl:849[inlined]
convolve_image(::Array{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8,8}},2}, ::Array{Float64,2})@Other: 12
top-level scope@Local: 1

更新:我设法解决了这个问题

在特定情况下,卷积导致r、g或b值>1.0。这种说法是行不通的

我目前的解决方案是将卷积限制在1.0(如果超过)。我目前没有求解<0.0的值,但这是微不足道的

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

您可以这样编写更新函数

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

不需要到处进行转换。

此问题也会随着代码的其他变体不断出现。我继续使用下面的代码得到以下类型的错误

错误类型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.
错误类型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.
代码

function extend_mat(M::AbstractMatrix, i, j)
    (h,w) = size(M)
    return M[clamp(i, 1, h), clamp(j, 1, w)]
end

也许您可以尝试将问题简化为“如何将数据类型A转换为数据类型B”?谢谢。我简化了这个问题。我还尝试了不同类型的重新解释的不同变体。Base还有一个
clamp
函数,因此您可以编写
if
语句,而不是所有
if
语句。((r,g,b),0,1)。谢谢!直到。我将应用它。尝试了钳制,但也没有在颜色值上传播,在无岛方法匹配中失败。但是钳制单个的R、G和B值,然后返回它们是有效的,这样我就可以摆脱if-else块。我尝试过这个方法,但不是在所有情况下都有效。取决于计算中发生的情况。如果该值超过1.0,则此操作失败。此外,如果它确实有效,则不需要单独的方法调用,只需在卷积方法本身中写出它即可。但这不起作用。:)但它真的失败了吗?在我的测试中,如果值超过1.0,颜色会饱和,产生与
钳制
相同的效果。至于你的另一点,这几乎不值得抱怨,对吧?无论如何,RGB类型的全部目的是简化这些计算,而不是使它们复杂化,通过让您跳过所有这些障碍。谢谢!我回去又看了一遍,发现它真的管用?但如果我写的稍微不同,它不会。因此,如果您按照答案中的格式编写函数,它可以正常工作,但是如果您按照以下格式编写:function(a,b,n)返回a+b*n,则失败。同样,在卷积函数本身中,如果我把它写成x+=y*n,它会失败,但是x=x+y*n可以工作。但这解决了很多不必要的代码,并教会了我一些新的东西,所以再次感谢。嗯。。这些失败是非常奇怪的。这些案例应该完全相同。你确定没有任何打字错误吗?我想说这肯定是一次奇怪的经历。但是代码时断时续地工作,我似乎无法解释原因。我现在已经重写了代码,所以我可以始终传入偏移数组(因为以前的版本没有按预期工作-图像边缘的错误,等等)。但是这个版本也面临着同样的夹紧问题。我怀疑到底发生了什么
conv_mk
包含类型为
RGBA{Normed{UInt8,8}
的值。当您将它们与一个数字相乘时,例如
Int
,乘积类型为
RGBA{Float32}
,该值可能超出范围0..1。当您将其重新分配回
conv_mk
时,尝试将其转换回
RGBA{Normed{UInt8,8}
。当数字在0..1内时,此操作成功,但当数字在0..1外时失败。结论是,您应该允许
conv_mk
保存“更宽”的类型,例如
typeof(first(img)*first(K))
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.
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.
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)