Подтвердить что ты не робот

Найти символы, похожие на глифически в Unicode?

Допустим, что у меня есть символы Ú, Ù, Ü. Все они похожи глифически на английский язык.

Есть ли список или алгоритм для этого:

  • Учитывая, что Ú или Ù или Ü верните английский язык U
  • Учитывая английский U, верните список всех U-подобных символов

Я не уверен, что кодовая точка символов Unicode одинакова для всех шрифтов? Если это так, я полагаю, что для этого может быть какой-то простой способ и эффективность?

UPDATE

Если вы используете Ruby, в этом случае есть драгоценный камень unicode-confusable, который может помочь в некоторых случаях.

4b9b3361

Ответ 1

Это не будет работать для всех условий, но один способ избавиться от большинства акцентов - это преобразовать символы в их разложенную форму, а затем выбросить комбинированные акценты:

# coding: utf8
import unicodedata as ud
s=u'U, Ù, Ú, Û, Ü, Ũ, Ū, Ŭ, Ů, Ű, Ų, Ư, Ǔ, Ǖ, Ǘ, Ǚ, Ǜ, Ụ, Ủ, Ứ, Ừ, Ử, Ữ, Ự'
print ud.normalize('NFD',s).encode('ascii','ignore')

Выход

U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U

Чтобы найти символы акцента, используйте что-то вроде:

import unicodedata as ud
import string

def asc(unichr):
    return ud.normalize('NFD',unichr).encode('ascii','ignore')

U = u''.join(unichr(i) for i in xrange(65536))
for c in string.letters:
    print u''.join(u for u in U if asc(u) == c)

Выход

aàáâãäåāăąǎǟǡǻȁȃȧḁạảấầẩẫậắằẳẵặ
bḃḅḇ
cçćĉċčḉ
dďḋḍḏḑḓ
eèéêëēĕėęěȅȇȩḕḗḙḛḝẹẻẽếềểễệ
fḟ
 :
etc.

Ответ 2

Непонятно, что вы здесь делаете.

  • Есть символы, чьи канонические разложения начинаются с одного и того же базового символа: e, é, ê, ë, ē, ĕ, é, ę, ě, ȅ, ȇ, ȩ, ḕ, ḗ, ḙ, ḛ, ḝ, ẹ, ẻ, ẽ, ế, ề, ể, ễ, ệ, e̳,... или s, ś, ŝ, ş, š, ş, ṡ, ṣ, ṥ, ṧ, ṩ,....

  • Есть символы, в которых совместимость разложения включают в себя конкретный символ: ᵉ, ₑ, ℯ, ⅇ, ⒠, ⓔ, ㋍, ㋎, e,... или s, s, ˢ, ẛ, ₨, ℁, ⒮, ⓢ, ㎧, ㎨, ㎮, ㎯, ㎰, ㎱, ㎲, ㎳, ㏛, ft, st, s,... или R, ᴿ, ₨, ℛ, ℜ, ℝ, Ⓡ, ㏚, R,....

  • Есть символы, которые просто выглядят одинаково в некоторых шрифтах: ß и β и β, или 3 и Ʒ и Ȝ и ȝ и ʒ и ӡ и ᴣ, или ɣ и ɤ и γ, или F и Ϝ и ϝ, или B и Β и В, или ∅ и ○ и 0 и O и 0 и 0 и 0 и 0, или 1 и l и я и Ⅰ и ᛁ и | и | и |,....

  • Символы, которые одинаковы без учета регистра, например s, S и s, или ss и Ss и SS и ß и ẞ,....

  • Символы, у которых все имеют одинаковое числовое значение, как и все эти значения для значения 1:1¹11߁1111 ୧ 11 ౹౼ 1111111 ፩ 1 ៱ ᠑ ᥇ ᧑᧚᪁᪑ ① ① ⑴ ⒈ ⓵ ❶➀➊꘡꣑꤁꧑꩑꯱𐄇𐅂𐅘𐅙𐅚 𐌠 𐏑 𐒡 𐡘 𐤖 𐩀 𐩽 𐭘 𐭸 𐹠 𐹠 🄂 Ⅰⅰꛦ ㆒ ㈠㊀𑁒𑁧.

    /li >
  • Символы, у которых все имеют одинаковую первичную силу сопоставления, как и все эти, такие же, как d: DdÐðĎďĐđ◌ͩᴰᵈᶞ◌ᷘ◌ᷙḊḋḌḍḎḏḐḑḒḓⅅⅆⅮⅾ Ⓓ ⓓ ꝹꝺDd𝐃𝐝𝐷𝑑𝑫𝒅𝒟𝒹𝓓𝓭𝔇𝔡𝔻𝕕𝕯𝖉𝖣𝖽𝗗𝗱𝘋𝘥𝘿𝙙𝙳𝚍 🄳 🅓 🅳 🇩. Обратите внимание, что некоторые из них недоступны с помощью какого-либо декомпозиции, но только через значения DUCET/UCA; например, достаточно общий ð или новый ꝺ можно приравнять к d только через первичное сравнение прочности UCA; то же самое с ƶ и z, ȼ и c и т.д.

  • Символы, которые одинаковы в определенных локалях, например æ и ae, или ä и ae, или ä и aa, или MacKinley и McKinley,.... Обратите внимание, что языковой стандарт может иметь большое значение, поскольку в некоторых локалях оба c и ç являются одинаковыми символами, а в других - нет; аналогично для n и ñ, или и á и ã,....

Некоторые из них могут быть обработаны. Некоторые не могут. Все они требуют разных подходов в зависимости от различных потребностей.

Какую цель ставите перед собой?

Ответ 3

Почему бы просто не сравнить глифы с чем-то вроде этого?

package similarglyphcharacterdetector;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.font.FontRenderContext;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

public class SimilarGlyphCharacterDetector {

    static char[] TEST_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890".toCharArray();
    static BufferedImage[] SAMPLES = null;

    public static BufferedImage drawGlyph(Font font, String string) {
        FontRenderContext frc = ((Graphics2D) new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_GRAY).getGraphics()).getFontRenderContext();

        Rectangle r= font.getMaxCharBounds(frc).getBounds();

        BufferedImage res = new BufferedImage(r.width, r.height, BufferedImage.TYPE_BYTE_GRAY);
        Graphics2D g = (Graphics2D) res.getGraphics();
        g.setBackground(Color.WHITE);
        g.fillRect(0, 0, r.width, r.height);
        g.setPaint(Color.BLACK);
        g.setFont(font);
        g.drawString(string, 0, r.height - font.getLineMetrics(string, g.getFontRenderContext()).getDescent());
        return res;
    }

    private static void drawSamples(Font f) {
        SAMPLES = new BufferedImage[TEST_CHARS.length];
        for (int i = 0; i < TEST_CHARS.length; i++)
            SAMPLES[i] = drawGlyph(f, String.valueOf(TEST_CHARS[i]));
    }

    private static int compareImages(BufferedImage img1, BufferedImage img2) {
        if (img1.getWidth() != img2.getWidth() || img1.getHeight() != img2.getHeight())
            throw new IllegalArgumentException();
        int d = 0;
        for (int y = 0; y < img1.getHeight(); y++) {
            for (int x = 0; x < img1.getWidth(); x++) {
                if (img1.getRGB(x, y) != img2.getRGB(x, y))
                    d++;
            }
        }
        return d;
    }

    private static int nearestSampleIndex(BufferedImage image, int maxDistance) {
        int best = Integer.MAX_VALUE;
        int bestIdx = -1;
        for (int i = 0; i < SAMPLES.length; i++) {
            int diff = compareImages(image, SAMPLES[i]);
            if (diff < best) {
                best = diff;
                bestIdx = i;
            }
        }
        if (best > maxDistance)
            return -1;
        return bestIdx;
    }

    public static void main(String[] args) throws Exception {
        Font f = new Font("FreeMono", Font.PLAIN, 13);
        drawSamples(f);
        HashMap<Character, StringBuilder> res = new LinkedHashMap<Character, StringBuilder>();
        for (char c : TEST_CHARS)
            res.put(c, new StringBuilder(String.valueOf(c)));
        int maxDistance = 5;
        for (int i = 0x80; i <= 0xFFFF; i++) {
            char c = (char)i;
            if (f.canDisplay(c)) {
                int n = nearestSampleIndex(drawGlyph(f, String.valueOf(c)), maxDistance);
                if (n != -1) {
                    char nc = TEST_CHARS[n];
                    res.get(nc).append(c);
                }
            }
        }
        for (Map.Entry<Character, StringBuilder> entry : res.entrySet())
            if (entry.getValue().length() > 1)
                System.out.println(entry.getValue());
    }
}

Вывод:

AÀÁÂÃÄÅĀĂĄǍǞȀȦΆΑΛАѦӒẠẢἈἉᾸᾹᾺᾼ₳Å
BƁƂΒБВЬḂḄḆ
CĆĈĊČƇΓЄГСὉℂⅭ
...