Skip to content

Different fonts #9

Open
Open

Description

@cormullion

This looks very interesting!

I think I'd find it useful to use different fonts - a way to measure degrees of similarity could be handy. And I suppose things like typosquatting are more likely to be done in circumstances where the font could be chosen to be misleading... (ie the bad guys use Arial instead of Helvetica... :).

What I'd probably do is try to read characters/strings via

http://juliagraphics.github.io/Luxor.jl/latest/examples/#Images-as-matrices

and then compare them. Would this be easy to do with VisualStringDistances?

Activity

  1. ericphanson commented on Aug 1, 2020

    @ericphanson
    Owner

    Cool, I'm glad you're interested! That looks like a great way. I briefly tried to do it via FreeTypeAbstraction.jl but I got lost in how that package works. The following seems to work!

    using Luxor, Colors, StaticArrays
    
    function string_to_matrix(str)
        m = @imagematrix begin
            background("black")
            sethue("white")
            fontface("Georgia")
            fontsize(24) # warning: big font size -> big matrix -> slow distance
            text(str, halign=:center, valign=:middle)
        end
        sa = SparseArrays.sparse(convert.(Colors.Gray, m) .> convert(Colors.Gray, ARGB32(0.0, 0.0, 0.0, 1.0)))
        return sa
    end
    
    using UnbalancedOptimalTransport, SparseArrays
    
    # `UnbalancedOptimalTransport` uses `DiscreteMeasure` to store the things it is comparing.
    # These have two relevant pieces: the density, which in this case is the opacity or weight we want to put on each pixel,
    # and the `set`, which here will just be the coordinates of the matrix.
    function UnbalancedOptimalTransport.DiscreteMeasure(sa::SparseMatrixCSC)
        coords = SVector{2,Float64}[]
        density = Float64[]
        I, J, V = findnz(sa)
        for n = eachindex(I, J, V)
            push!(coords, SVector{2, Float64}(I[n], J[n]))
            push!(density, V[n])
        end
        return DiscreteMeasure(density, coords)
    end
    
    function visual_distance2(str1, str2; D = UnbalancedOptimalTransport.KL(1.0), ϵ = 0.01)
        sa1 = string_to_matrix(str1)
        sa2 = string_to_matrix(str2)
        return sinkhorn_divergence!(D, DiscreteMeasure(sa1), DiscreteMeasure(sa2), ϵ)
    end

    One difficulty is if the image gets too big, visual_distance gets very slow; with font size 24 it seems OK. I actually don't use VisualStringDistances here at all, just the underlying algorithm in UnbalancedOptimalTransport.jl. Let me know if you have any luck with this or run into any troubles :)

  2. cormullion commented on Aug 2, 2020

    @cormullion
    Author

    Thanks, this works great - I can get all sorts of measurements from comparing strings and fonts...

    julia> # test - should be zero
    compare("O", "O", font1="JuliaMono-Regular", font2="JuliaMono-Regular")
    O in JuliaMono-Regular  vs O in JuliaMono-Regular:
    0.0010819308549554307
    
    julia> # compare different glyphs in the same font
    compare("O", "0", font1="JuliaMono-Regular", font2="JuliaMono-Regular")
    O in JuliaMono-Regular  vs 0 in JuliaMono-Regular:
    26.77476852981517
    
    julia> compare("O", "0", font1="SFMono-Regular", font2="SFMono-Regular")
    O in SFMono-Regular  vs 0 in SFMono-Regular:
    39.771611214031
    
    julia> # compare different glyphs in the same font
    compare("&", "\$", font1="JuliaMono-Regular", font2="JuliaMono-Regular")
    & in JuliaMono-Regular  vs $ in JuliaMono-Regular:
    71.03373098044722
    
    julia> compare("&", "\$", font1="SFMono-Regular", font2="SFMono-Regular")
    & in SFMono-Regular  vs $ in SFMono-Regular:
    78.41157442985032
    
    julia> # comparing same glyphs in different fonts
    compare("0", "0", font1="JuliaMono-Regular", font2="SFMono-Regular")
    0 in JuliaMono-Regular  vs 0 in SFMono-Regular:
    23.482812287382792
    
    julia> compare("O", "O", font1="JuliaMono-Regular", font2="SFMono-Regular")
    O in JuliaMono-Regular  vs O in SFMono-Regular:
    15.58672859276412
    

    Literally hours of fun... :)

    By the way, you can add dimensions to the matrix to improve performance, the default is 250×250:

    m = @imagematrix begin
                background("black")
                sethue("white")
                fontface(font)
                fontsize(24) # warning: big font size -> big matrix -> slow distance
                text(str, halign=:center, valign=:middle)
            end 30 30
    

    Thanks!

    PS: Sinkhorn Divergence would be a good name for my new band... :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions