tabla letras ejemplos consorcio codigo unicode glyph

letras - Encuentra caracteres que son similares glíficamente en Unicode?



unicode utf-8 (3)

Digamos que tengo los personajes Ú, Ù, Ü. Todos son similares glíficamente a la U española.

¿Hay alguna lista o algoritmo para hacer esto?

  • Dado un Ú o Ù o Ü devuelve el inglés U
  • Dada una U en inglés, devuelve la lista de todos los personajes U-similares

No estoy seguro de si el punto de código de los caracteres Unicode es el mismo para todas las fuentes. Si es así, supongo que podría haber alguna manera fácil y eficiente de hacerlo.

ACTUALIZAR

Si está usando Ruby, hay una gema disponible unicode-confusable para esto que puede ayudar en algunos casos.


Esto no funcionará para todas las condiciones, pero una manera de deshacerse de la mayoría de los acentos es convertir los personajes a su forma descompuesta, luego descartar los acentos combinados:

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

Salida

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

Para encontrar caracteres de acento, use algo como:

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)

Salida

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


No está muy claro qué es lo que está pidiendo que haga aquí.

  • Hay personajes cuyas descomposiciones canónicas comienzan todas con el mismo carácter base: e, é, ê, ë, ē, ĕ, è, ê, ì, ȅ, ȩ, ḕ, ė, ė, ḗ, ḗ, ḙ, ȇ, ḕ, ḗ, ḙ, ȇ, ḕ, ḗ, ḙ, ḛ, ȇ ẻ, ế, ề, ể, ễ, ệ, e̳, ... o s, ś, ŝ, ş, or, or, or, š, or, or, š, š, or, or, or, š, or, or, or, š, or, or, or, š, or, or, ṣ, ṧ, š,.

  • Hay caracteres cuyas descomposiciones de compatibilidad incluyen un caracter particular: ᵉ, ₑ, ℯ, ⒠, ⓔ, ㋍,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ㎨, ㎮, ㎯, ㎰, ㎲, ㏛, ㏛, ㏛,,,,, ft, st, s, ... o R, ᴿ, ₨, ℛ, ℜ, ℝ, Ⓡ, R, ....

  • Hay caracteres que parecen similares en algunas fuentes: ß y β y β, o 3 y Ʒ y Ȝ y ȝ y ʒ y ᴣ y ɣ y ɤ y γ, o F y Ϝ y ϝ, o B y Β y В, o ∅ y ○ y 0 y O y 0 y 0 y 0 y 0, o 1 y l e I y Ⅰ y ᛁ y | y | y |, ....

  • Caracteres que son los mismos sin distinción de mayúsculas y minúsculas , como s y S y s, o ss y Ss y SS y ß y ẞ, ....

  • Los caracteres que tienen todos el mismo valor numérico , como todos estos para el valor 1 : 1¹11߁1111 ୧ 11 ౹౼ 1111111 ፩ 1 ៱ ៱ ៱ ៱ ៱ ៱ 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11.

  • Los caracteres que tienen la misma fuerza de intercalación primaria , como todos los que son iguales a d : DdÐðĎďĐđ◌ͩᴰᵈᶞ◌ᷘ◌ᷙḊḋḌḍḎḏḐḑḒḓⅅⅆⅮⅾ ĎďĐđ◌ͩᴰᵈᶞ◌ᷘ◌ᷙḊḋḌḍḎḏḐḑḒḓⅅⅆⅮⅾ 𝐃𝐝𝐷𝑑𝑫𝒅𝒟𝒹𝓓𝓭𝔇𝔡𝔻𝕕𝕯𝖉𝖣𝖽𝗗𝗱𝘋𝘥𝘿𝙙𝙳𝚍Dd𝐃𝐝𝐷𝑑𝑫𝒅𝒟𝒹𝓓𝓭𝔇𝔡𝔻𝕕𝕯𝖉𝖣𝖽𝗗𝗱𝘋𝘥𝘿𝙙𝙳𝚍 🄳 𝐃𝐝𝐷𝑑𝑫𝒅𝒟𝒹𝓓𝓭𝔇𝔡𝔻𝕕𝕯𝖉𝖣𝖽𝗗𝗱𝘋𝘥𝘿𝙙𝙳𝚍 𝐃𝐝𝐷𝑑𝑫𝒅𝒟𝒹𝓓𝓭𝔇𝔡𝔻𝕕𝕯𝖉𝖣𝖽𝗗𝗱𝘋𝘥𝘿𝙙𝙳𝚍 𝐃𝐝𝐷𝑑𝑫𝒅𝒟𝒹𝓓𝓭𝔇𝔡𝔻𝕕𝕯𝖉𝖣𝖽𝗗𝗱𝘋𝘥𝘿𝙙𝙳𝚍. Tenga en cuenta que algunos de ellos no son accesibles a través de ningún tipo de descomposición, sino solo a través de los valores DUCET / UCA; por ejemplo, la ð bastante común o la nueva ꝺ se pueden equiparar a d solo a través de una comparación de la fuerza UCA primaria; lo mismo con ƶ y z, ȼ y c, etc.

  • Caracteres que son iguales en ciertos lugares , como æ y ae, o ä y ae, o ä y aa, o MacKinley y McKinley, .... Tenga en cuenta que la configuración regional puede marcar una gran diferencia, ya que en algunos entornos tanto c como ç son el mismo carácter, mientras que en otros no; del mismo modo para n y ñ, o a y á y ã, ....

Algunos de estos pueden ser manejados. Algunos no pueden. Todos requieren diferentes enfoques dependiendo de las diferentes necesidades.

¿Cuál es tu verdadero objetivo?


¿Por qué no simplemente comparar glifos con algo como esto?

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()); } }

Salida:

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