17

Ú、Ù、Ü という文字があるとします。それらはすべて英語の U に字形的に似ています。

これを行うためのリストまたはアルゴリズムはありますか:

  • Ú、Ù、または Ü を指定すると、英語の U が返されます。
  • 英語の U を指定すると、U に類似したすべての文字のリストを返します

Unicode 文字のコード ポイントがすべてのフォントで同じかどうかわかりません。もしそうなら、これを行うための簡単で効率的な方法があると思いますか?

アップデート

Ruby を使用している場合、場合によっては、このためにunicode-confusableを使用できる gemが役立つ場合があります。

4

3 に答える 3

31

ここで何をしようとしているのかは非常に不明確です。

  • 正規分解がすべて同じ基本文字で始まる文字があります:e、é、ê、ë、ē、ĕ、ė、ę、ě、ȅ、ȇ、ȩ、ḕ、ḗ、ḙ、ḛ、ḝ、ẹ 、ẻ、ẽ、ế、ề、ể、ễ、ệ、ē、…またはs、ś、ŝ、ş、š、ș、ṡ、ṣ、ṥ、ṧ、ṩ、…。

  • 互換性の分解にすべて特定の文字が含まれる文字があります:ᵉ、ₑ、ℯ、ⅇ、⒠、ⓔ、㋍、㋎、e、…またはs、ſ、ˢ、ẛ、₨、℁、⒮、ⓢ、 ㎨、㎮、㎯、㎰、㎱、㎲、㎳、㏛、ſt、st、s、…またはR、ᴿ、₨、ℛ、ℜ、ℝ、Ⓡ、㏚、

  • 一部のフォントでは、たまたま似ている文字があります。ßとβとϐ、または3とƷとȜとȝとʒとӡとᴣ、またはɣとɤとγ、またはFとϜとϝ、またはBおよびΒとВ、または∅と○と0とOと০と੦と౦と૦、または1とlとIとⅠとᛁと| とǀと∣、…。

  • sとSとſ、またはssとSsとSSとßとẞのように、大文字と小文字を区別せずに同じ文字…。

  • すべてが同じ持っているキャラクターの数値を値のため、これらすべてのように、1:1¹11߁1111୧11౹౼1111111፩1៱᠑᥇᧑᧚᪁᪑᭑᮱᱁᱑₁⅟①⑴⒈ ⓵❶➀➊꘡꣑꤁꧑꩑꯱Ⅰⅰꛦ㆒㈠㊀ 。

  • dと同じすべての文字のように、すべて同じ一次照合強度を持つ文字:DdÐðĎďĐđ◌ͩᴰᵈᶞ◌ᷘ◌ᷙḊḋḌḍḎḏḐḑḒḓⅅⅅ それらのいくつかは、いかなる種類の分解によってもアクセスできず、DUCET/UCA値によってのみアクセス可能であることに注意してください。たとえば、かなり一般的なðまたは新しいꝺは、主要なUCA強度の比較によってのみdと同等になります。ƶとz、ȼとcなどと同じです。

  • æとae、またはäとae、またはäとaa、またはMacKinleyとMcKinleyなど、特定のロケールで同じ文字…。一部のロケールではcとçの両方が同じ文字であるのに対し、他のロケールではそうではないため、ロケールは非常に大きな違いを生む可能性があることに注意してください。同様に、nとñ、またはaとáとã、…。

これらのいくつかは処理できます。できない人もいます。ニーズに応じて、すべて異なるアプローチが必要です。

あなたの本当の目標は何ですか?

于 2011-01-31T00:08:08.773 に答える
12

これはすべての条件で機能するわけではありませんが、ほとんどのアクセントを取り除く方法の 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.
于 2011-01-31T08:04:06.457 に答える
5

グリフをこのようなものと比較してみませんか?

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ĆĈĊČƇΓЄГСὉℂⅭ
...
于 2012-02-29T20:25:22.727 に答える