GroundingPI / tests /test_render.py
FanLR's picture
Fix Chinese OCR labels with bundled CJK font
8e0d79f verified
Raw History Blame Contribute Delete
4.04 kB
import unittest
from PIL import Image, ImageDraw
from grounding_demo.protocol import Primitive
from grounding_demo.render import draw_primitives, layout_box_labels, _font, PURPLE
class RenderRegression(unittest.TestCase):
def test_chinese_and_mixed_text_have_real_glyphs(self):
font = _font(24, "中文 OCR:姓名,日期(2026年)")
missing = bytes(font.getmask("\u0378"))
masks = []
for char in "姓名出生日期地址簡體繁體,:()":
with self.subTest(char=char):
mask = bytes(font.getmask(char))
self.assertNotEqual(mask, missing)
self.assertTrue(any(mask))
masks.append(mask)
self.assertEqual(len(set(masks[:6])), 6)
def test_chinese_badges_measure_and_draw_with_the_same_font(self):
text = "中文 OCR:测试标签 2026年(示例)"
primitives = [Primitive(text, (100, 300, 800, 500))]
badge = layout_box_labels(primitives, 1000, 700, _font(20))[0]
self.assertEqual(badge["text"], text)
expected = ImageDraw.Draw(Image.new("RGB", (1, 1))).textbbox(
(0, 0), text, font=_font(20, text)
)
self.assertEqual(badge["text_bounds"], expected)
x1, y1, x2, y2 = badge["box"]
self.assertEqual(x2-x1, expected[2]-expected[0]+8)
self.assertEqual(y2-y1, expected[3]-expected[1]+8)
rendered = draw_primitives(Image.new("RGB", (1000, 700), "white"), primitives)
self.assertEqual(rendered.size, (1000, 700))
def test_long_chinese_badges_stay_inside_canvas_without_changing_text_data(self):
text = "这是一段很长的中文识别结果,包含标点和 English 2026。"*4
primitive = Primitive(text, (900, 0, 999, 999))
badges = layout_box_labels([primitive], 140, 120, _font(18))
self.assertEqual(len(badges), 1)
badge = badges[0]
self.assertEqual(badge["label"], text)
self.assertTrue(badge["text"].endswith("…"))
x1,y1,x2,y2 = badge["box"]
self.assertTrue(0<=x1<x2<=140 and 0<=y1<y2<=120)
def test_dense_labels_are_unique_visible_and_do_not_overlap(self):
boxes = [Primitive(f"category {i}", (50+(i%5)*180, 50+(i//5)*210,
150+(i%5)*180, 190+(i//5)*210)) for i in range(20)]
boxes += [Primitive("category 0", (700, 800, 850, 950))]
original = list(boxes)
labels = layout_box_labels(boxes, 1000, 1000, _font(16))
self.assertEqual(len(labels), 20)
self.assertEqual(len({row["label"] for row in labels}), 20)
for i, row in enumerate(labels):
x1,y1,x2,y2=row["box"]
self.assertTrue(0<=x1<x2<=1000 and 0<=y1<y2<=1000)
for other in labels[i+1:]:
a,b,c,d=other["box"]
self.assertFalse(x1<c and a<x2 and y1<d and b<y2)
self.assertEqual(boxes, original)
def test_large_late_region_does_not_erase_small_target(self):
image = Image.new("RGB", (1000, 1000), "white")
small = Primitive("boat", (300, 400, 350, 450))
large = Primitive("lake", (0, 300, 999, 999))
rendered = draw_primitives(image, [small, large])
self.assertEqual(rendered.getpixel((300, 425)), PURPLE)
self.assertEqual(rendered.getpixel((500, 700)), (255, 255, 255))
def test_nested_geometry_is_not_filtered(self):
image = Image.new("RGB", (1000, 1000), "white")
boxes = [Primitive("target", (i, i, 999-i, 999-i)) for i in range(100, 401, 100)]
rendered = draw_primitives(image, boxes)
for i in range(100, 401, 100):
self.assertEqual(rendered.getpixel((i, 500)), PURPLE)
def test_small_and_edge_label_canvas_is_safe(self):
image = Image.new("RGB", (32, 32), "white")
result = draw_primitives(image, [Primitive("long OCR text "*10, (970, 0, 999, 999))])
self.assertEqual(result.size, image.size)
if __name__ == "__main__":
unittest.main()