| """ | |
| generate_dummy_forms.py | |
| ======================= | |
| Generates dummy-filled civil registry forms by overlaying | |
| handwritten-style text onto the ACTUAL blank PDF form templates. | |
| Coordinates measured directly from grid images (200 DPI render). | |
| Form 102: 1700 x 2800 px | |
| Form 103: 1700 x 2600 px | |
| Form 97: 1700 x 2600 px | |
| Form 90: 1700 x 2600 px | |
| Usage: | |
| python generate_dummy_forms.py | |
| """ | |
| import os, random | |
| import fitz | |
| from PIL import Image, ImageDraw, ImageFont | |
| OUT_DIR = "dummy_forms" | |
| FORMS_DIR = "CRNN+CTC" | |
| os.makedirs(OUT_DIR, exist_ok=True) | |
| PDF_102 = os.path.join(FORMS_DIR, "FORM 102 (BIRTH CERTIFICATE).pdf") | |
| PDF_103 = os.path.join(FORMS_DIR, "FORM 103 (DEATH CERTIFICATE).pdf") | |
| PDF_97 = os.path.join(FORMS_DIR, "FORM 97 (MARRIAGE CERTIFICATE).pdf") | |
| PDF_90 = os.path.join(FORMS_DIR, "FORM 90-MARRIAGE-LICENCE-FORM.pdf") | |
| HW_FONT = "C:/Windows/Fonts/Inkfree.ttf" | |
| def get_font(size): | |
| try: return ImageFont.truetype(HW_FONT, size) | |
| except: return ImageFont.load_default() | |
| # ββ Filipino dummy data ββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| FM = ["Juan","Pedro","Jose","Carlos","Roberto","Eduardo","Miguel","Antonio","Ramon","Fernando","Andres","Ricardo"] | |
| FF = ["Maria","Rosa","Elena","Luisa","Carmen","Gloria","Lourdes","Felicitas","Conchita","Remedios","Natividad","Cristina"] | |
| MID = ["dela Cruz","Reyes","Santos","Garcia","Lopez","Mendoza","Torres","Aquino","Bautista","Villanueva","Castro","Ramos"] | |
| LN = ["Santos","Reyes","Cruz","Garcia","Mendoza","Torres","Lopez","Ramos","Bautista","Aquino","Villanueva","Castro"] | |
| CTY = ["Tarlac City","Makati City","Quezon City","Manila","Caloocan","Pasig City","Marikina City","Malabon"] | |
| PRV = ["Tarlac","Metro Manila","Cavite","Laguna","Bulacan","Pampanga","Rizal","Batangas"] | |
| HSP = ["Tarlac Provincial Hospital","Ospital ng Maynila","Philippine General Hospital", | |
| "Quezon City Medical Center","San Juan de Dios Hospital","Capitol Medical Center"] | |
| REL = ["Roman Catholic","Iglesia ni Cristo","Protestant","Born Again Christian"] | |
| OCC = ["Farmer","Teacher","Engineer","Driver","Housewife","Businessman","Carpenter","Nurse","Laborer"] | |
| CST = ["Single","Married","Widowed"] | |
| MON = ["January","February","March","April","May","June", | |
| "July","August","September","October","November","December"] | |
| VEN = ["Saint Joseph Parish","City Hall","San Sebastian Cathedral","Sto. Nino Parish","Saint Peter Parish"] | |
| COD = ["Cardiopulmonary Arrest","Pneumonia","Myocardial Infarction","Renal Failure","Sepsis"] | |
| rm = lambda: random.choice(FM) | |
| rf = lambda: random.choice(FF) | |
| rmd = lambda: random.choice(MID) | |
| rln = lambda: random.choice(LN) | |
| rc = lambda: random.choice(CTY) | |
| rp = lambda: random.choice(PRV) | |
| rd = lambda: str(random.randint(1, 28)) | |
| rmo = lambda: random.choice(MON) | |
| ry = lambda s=1960, e=2005: str(random.randint(s, e)) | |
| rrn = lambda pfx: f"{random.randint(2020,2025)}-{pfx}-{random.randint(1000,9999):05d}" | |
| # ββ Core helpers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def pdf_to_image(pdf_path, dpi=200): | |
| doc = fitz.open(pdf_path) | |
| mat = fitz.Matrix(dpi/72, dpi/72) | |
| pix = doc[0].get_pixmap(matrix=mat) | |
| img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples) | |
| doc.close() | |
| return img | |
| X_OFFSET = 170 # shift all fields right β increase if still too far left | |
| def hw(draw, x, y, text, size=20, color="#1a1a6e"): | |
| font = get_font(size) | |
| ox = random.randint(-1, 1) | |
| oy = random.randint(-1, 1) | |
| draw.text((x + X_OFFSET + ox, y+oy), str(text), fill=color, font=font) | |
| def save(img, name): | |
| path = os.path.join(OUT_DIR, name) | |
| img.save(path, dpi=(200, 200)) | |
| print(f" Saved: {path}") | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # FORM 102 β Certificate of Live Birth (1700 x 2800) | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def generate_form_102(n): | |
| img, draw = pdf_to_image(PDF_102), None | |
| draw = ImageDraw.Draw(img) | |
| def f(x, y, text, size=20): hw(draw, x, y, text, size) | |
| # ββ Header ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| f(178, 322, rp()) # Province | |
| f(1255, 322, rrn("BC")) # Registry No | |
| f(178, 370, rc()) # City/Municipality | |
| # ββ CHILD βββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| f(205, 438, rm()) # 1. NAME First | |
| f(600, 438, rmd()) # Middle | |
| f(1060, 438, rln()) # Last | |
| f(205, 495, random.choice(["Male","Female"])) # 2. SEX | |
| f(585, 495, rd()) # 3. DATE OF BIRTH Day | |
| f(742, 495, rmo()) # Month | |
| f(975, 495, ry(1970,2024)) # Year | |
| f(295, 552, random.choice(HSP)) # 4. PLACE OF BIRTH Hospital | |
| f(738, 552, rc()) # City | |
| f(1120, 552, rp()) # Province | |
| f(205, 603, "Single") # 5a. TYPE OF BIRTH | |
| f(900, 603, "First") # 5c. BIRTH ORDER | |
| # ββ MOTHER ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| f(205, 695, rf()) # 7. MAIDEN NAME First | |
| f(600, 695, rmd()) # Middle | |
| f(1060, 695, rln()) # Last | |
| f(205, 752, "Filipino") # 8. CITIZENSHIP | |
| f(685, 752, random.choice(REL)) # 9. RELIGION | |
| f(645, 810, random.choice(OCC)) # 11. OCCUPATION | |
| f(1415, 810, str(random.randint(20,50))) # 12. AGE | |
| f(295, 870, f"{random.randint(1,999)} Rizal St., Brgy. San Antonio") # 13. RESIDENCE | |
| f(738, 870, rc()) | |
| f(1120, 870, rp()) | |
| # ββ FATHER ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| f(205, 985, rm()) # 14. NAME First | |
| f(600, 985, rmd()) # Middle | |
| f(1060, 985, rln()) # Last | |
| f(205, 1048, "Filipino") # 15. CITIZENSHIP | |
| f(425, 1048, random.choice(REL)) # 16. RELIGION | |
| f(785, 1048, random.choice(OCC)) # 17. OCCUPATION | |
| f(1415, 1048, str(random.randint(22,55))) # 18. AGE | |
| f(295, 1105, f"{random.randint(1,999)} Mabini St., Brgy. Poblacion") # 19. RESIDENCE | |
| f(738, 1105, rc()) | |
| f(1120, 1105, rp()) | |
| # ββ MARRIAGE OF PARENTS ββββββββββββββββββββββββββββββββββββββ | |
| f(175, 1215, rmo()) # 20a. DATE Month | |
| f(385, 1215, rd()) # Day | |
| f(510, 1215, ry(1960,2010)) # Year | |
| f(762, 1215, rc()) # 20b. PLACE City | |
| f(1062, 1215, rp()) # Province | |
| save(img, f"form_102_{n:03d}.png") | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # FORM 103 β Certificate of Death (1700 x 2600) | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def generate_form_103(n): | |
| img = pdf_to_image(PDF_103) | |
| draw = ImageDraw.Draw(img) | |
| def f(x, y, text, size=20): hw(draw, x, y, text, size) | |
| # ββ Header ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| f(178, 218, rp()) # Province | |
| f(1255, 218, rrn("DC")) # Registry No | |
| f(178, 260, rc()) # City/Municipality | |
| # ββ Row 1 NAME + 2 SEX ββββββββββββββββββββββββββββββββββββββ | |
| f(178, 335, rm()) # 1. NAME First | |
| f(535, 335, rmd()) # Middle | |
| f(878, 335, rln()) # Last | |
| f(1325, 335, random.choice(["Male","Female"])) # 2. SEX | |
| # ββ Row 3 DATE OF DEATH + 4 DATE OF BIRTH + 5 AGE βββββββββββ | |
| f(178, 418, f"{rd()} {rmo()} {ry(2010,2025)}") # 3. DATE OF DEATH | |
| f(618, 418, rd()) # 4. DATE OF BIRTH Day | |
| f(712, 418, rmo()) # Month | |
| f(830, 418, ry(1930,1990)) # Year | |
| f(1055, 418, str(random.randint(30,90))) # 5. AGE | |
| # ββ Row 6 PLACE OF DEATH + 7 CIVIL STATUS βββββββββββββββββββ | |
| f(178, 480, f"{random.choice(HSP)}, {rc()}") # 6. PLACE OF DEATH | |
| f(1255, 480, random.choice(CST)) # 7. CIVIL STATUS | |
| # ββ Row 8 RELIGION + 9 CITIZENSHIP + 10 RESIDENCE βββββββββββ | |
| f(178, 548, random.choice(REL)) # 8. RELIGION | |
| f(555, 548, "Filipino") # 9. CITIZENSHIP | |
| f(818, 548, f"{random.randint(1,999)} Rizal St., {rc()}") # 10. RESIDENCE | |
| # ββ Row 11 OCCUPATION + 12 FATHER + 13 MOTHER βββββββββββββββ | |
| f(178, 628, random.choice(OCC)) # 11. OCCUPATION | |
| f(428, 628, f"{rm()} {rmd()} {rln()}") # 12. NAME OF FATHER | |
| f(1028, 628, f"{rf()} {rmd()} {rln()}") # 13. MAIDEN NAME OF MOTHER | |
| # ββ 19b CAUSES OF DEATH ββββββββββββββββββββββββββββββββββββββ | |
| f(368, 905, random.choice(COD)) # Immediate cause | |
| f(368, 953, random.choice(["Hypertensive CVD","COPD","Septicemia"])) # Antecedent | |
| f(368, 1003, random.choice(["Hypertension","Diabetes Mellitus","Old Age"])) # Underlying | |
| save(img, f"form_103_{n:03d}.png") | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # FORM 97 β Certificate of Marriage (1700 x 2600) | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def generate_form_97(n): | |
| img = pdf_to_image(PDF_97) | |
| draw = ImageDraw.Draw(img) | |
| def f(x, y, text, size=20): hw(draw, x, y, text, size) | |
| # ββ Header ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| f(178, 242, rp()) # Province | |
| f(1385, 242, rrn("MC")) # Registry No | |
| f(178, 282, rc()) # City/Municipality | |
| # ββ Row 1 NAME βββββββββββββββββββββββββββββββββββββββββββββββ | |
| # HUSBAND # WIFE | |
| f(178, 372, rm()); f(892, 372, rf()) # First | |
| f(178, 410, rmd()); f(892, 410, rmd()) # Middle | |
| f(178, 448, rln()); f(892, 448, rln()) # Last | |
| # ββ Row 2a DATE OF BIRTH / 2b AGE βββββββββββββββββββββββββββ | |
| h_dob_y = ry(1975, 2000) | |
| w_dob_y = ry(1975, 2000) | |
| h_age = str(random.randint(18,45)) | |
| w_age = str(random.randint(18,45)) | |
| f(178, 493, rd()); f(892, 493, rd()) # Day | |
| f(308, 493, rmo()); f(1022, 493, rmo()) # Month | |
| f(478, 493, h_dob_y); f(1188, 493, w_dob_y) # Year | |
| f(635, 493, h_age); f(1348, 493, w_age) # Age | |
| # ββ Row 3 PLACE OF BIRTH βββββββββββββββββββββββββββββββββββββ | |
| f(178, 548, rc()); f(892, 548, rc()) # City | |
| f(418, 548, rp()); f(1122, 548, rp()) # Province | |
| # ββ Row 4a SEX / 4b CITIZENSHIP βββββββββββββββββββββββββββββ | |
| f(178, 618, "Male"); f(892, 618, "Female") | |
| f(352, 618, "Filipino"); f(1062, 618, "Filipino") | |
| # ββ Row 5 RESIDENCE ββββββββββββββββββββββββββββββββββββββββββ | |
| f(178, 672, f"{random.randint(1,999)} Rizal St., {rc()}, {rp()}") | |
| f(892, 672, f"{random.randint(1,999)} Mabini St., {rc()}, {rp()}") | |
| # ββ Row 6 RELIGION βββββββββββββββββββββββββββββββββββββββββββ | |
| f(178, 768, random.choice(REL)); f(892, 768, random.choice(REL)) | |
| # ββ Row 7 CIVIL STATUS βββββββββββββββββββββββββββββββββββββββ | |
| f(178, 835, "Single"); f(892, 835, "Single") | |
| # ββ Row 8 NAME OF FATHER βββββββββββββββββββββββββββββββββββββ | |
| f(178, 902, rm()); f(892, 902, rm()) # First | |
| f(368, 902, rmd()); f(1088, 902, rmd()) # Middle | |
| f(562, 902, rln()); f(1278, 902, rln()) # Last | |
| # ββ Row 9 CITIZENSHIP (Father) βββββββββββββββββββββββββββββββ | |
| f(178, 985, "Filipino"); f(892, 985, "Filipino") | |
| # ββ Row 10 NAME OF MOTHER ββββββββββββββββββββββββββββββββββββ | |
| f(178, 1050, rf()); f(892, 1050, rf()) # First | |
| f(368, 1050, rmd()); f(1088, 1050, rmd()) # Middle | |
| f(562, 1050, rln()); f(1278, 1050, rln()) # Last | |
| # ββ Row 11 CITIZENSHIP (Mother) ββββββββββββββββββββββββββββββ | |
| f(178, 1138, "Filipino"); f(892, 1138, "Filipino") | |
| # ββ Row 15 PLACE OF MARRIAGE βββββββββββββββββββββββββββββββββ | |
| f(222, 1578, random.choice(VEN)) # Office/Church | |
| f(698, 1578, rc()) # City | |
| f(1102, 1578, rp()) # Province | |
| # ββ Row 16 DATE OF MARRIAGE ββββββββββββββββββββββββββββββββββ | |
| f(178, 1638, rd()) # Day | |
| f(308, 1638, rmo()) # Month | |
| f(502, 1638, ry(2015,2025)) # Year | |
| f(1282, 1638, f"{random.randint(8,11)}:00 {random.choice(['AM','PM'])}") # 17. TIME | |
| save(img, f"form_97_{n:03d}.png") | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # FORM 90 β Application for Marriage License (1700 x 2600) | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def generate_form_90(n): | |
| img = pdf_to_image(PDF_90) | |
| draw = ImageDraw.Draw(img) | |
| def f(x, y, text, size=20): hw(draw, x, y, text, size) | |
| # ββ Header ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| f(178, 232, rp()) # Province | |
| f(1252, 232, rrn("ML")) # Registry No | |
| f(178, 272, rc()) # City/Municipality | |
| f(1002, 308, rrn("LN")) # Marriage License No | |
| f(1002, 348, f"{rmo()} {rd()}, {ry(2023,2025)}") # Date of Issuance | |
| # ββ 1. NAME OF APPLICANT βββββββββββββββββββββββββββββββββββββ | |
| # GROOM (left) # BRIDE (right) | |
| f(102, 708, rm()); f(872, 708, rf()) # First | |
| f(102, 752, rmd()); f(872, 752, rmd()) # Middle | |
| f(102, 795, rln()); f(872, 795, rln()) # Last | |
| # ββ 2. DATE OF BIRTH / AGE βββββββββββββββββββββββββββββββββββ | |
| f(102, 835, rd()); f(872, 835, rd()) # Day | |
| f(228, 835, rmo()); f(998, 835, rmo()) # Month | |
| f(388, 835, ry(1980,2005)); f(1158, 835, ry(1980,2005)) # Year | |
| f(568, 835, str(random.randint(18,45))); f(1338, 835, str(random.randint(18,45))) # Age | |
| # ββ 3. PLACE OF BIRTH ββββββββββββββββββββββββββββββββββββββββ | |
| f(102, 882, rc()); f(872, 882, rc()) # City | |
| f(288, 882, rp()); f(1058, 882, rp()) # Province | |
| # ββ 4. SEX / CITIZENSHIP βββββββββββββββββββββββββββββββββββββ | |
| f(102, 952, "Male"); f(872, 952, "Female") | |
| f(268, 952, "Filipino"); f(1038, 952, "Filipino") | |
| # ββ 5. RESIDENCE βββββββββββββββββββββββββββββββββββββββββββββ | |
| f(102, 1015, f"{random.randint(1,999)} Rizal St., {rc()}") | |
| f(872, 1015, f"{random.randint(1,999)} Mabini St., {rc()}") | |
| # ββ 6. RELIGION ββββββββββββββββββββββββββββββββββββββββββββββ | |
| f(102, 1100, random.choice(REL)) | |
| f(872, 1100, random.choice(REL)) | |
| # ββ 7. CIVIL STATUS ββββββββββββββββββββββββββββββββββββββββββ | |
| f(102, 1175, "Single"); f(872, 1175, "Single") | |
| # ββ 12. NAME OF FATHER βββββββββββββββββββββββββββββββββββββββ | |
| f(102, 1562, rm()); f(872, 1562, rm()) # First | |
| f(272, 1562, rmd()); f(1042, 1562, rmd()) # Middle | |
| f(462, 1562, rln()); f(1232, 1562, rln()) # Last | |
| # ββ 13. CITIZENSHIP (Father) βββββββββββββββββββββββββββββββββ | |
| f(102, 1642, "Filipino"); f(872, 1642, "Filipino") | |
| # ββ 15. MAIDEN NAME OF MOTHER ββββββββββββββββββββββββββββββββ | |
| f(102, 1762, rf()); f(872, 1762, rf()) # First | |
| f(272, 1762, rmd()); f(1042, 1762, rmd()) # Middle | |
| f(462, 1762, rln()); f(1232, 1762, rln()) # Last | |
| # ββ 16. CITIZENSHIP (Mother) βββββββββββββββββββββββββββββββββ | |
| f(102, 1842, "Filipino"); f(872, 1842, "Filipino") | |
| save(img, f"form_90_{n:03d}.png") | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # MAIN | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| if __name__ == "__main__": | |
| COUNT = 1 # β set to 30 when alignment is confirmed | |
| missing = [p for p in [PDF_102, PDF_103, PDF_97, PDF_90] if not os.path.exists(p)] | |
| if missing: | |
| print("ERROR: Missing PDF form files:") | |
| for m in missing: print(f" {m}") | |
| exit(1) | |
| print(f"Generating {COUNT} dummy forms per type ({COUNT*4} total)...") | |
| print(f"Output: {os.path.abspath(OUT_DIR)}/\n") | |
| for i in range(1, COUNT + 1): | |
| print(f"[{i}/{COUNT}]") | |
| generate_form_102(i) | |
| generate_form_103(i) | |
| generate_form_97(i) | |
| generate_form_90(i) | |
| print(f"\nDone! {COUNT*4} forms saved to: {os.path.abspath(OUT_DIR)}/") | |
| print("\nNext: upload dummy_forms/ to Roboflow and annotate field bounding boxes.") | |