Kuvasi paljastaa tarkalleen syyllisen! Tuo cv2.equalizeHist (joka minun piti
olla "fiksu" esteettC6myyshaku) teki juuri pC$invastoin kuin toivoimme.
Koska WhatsAppin chat-taustalla on se hento "doodle"-kuviointi, kontrastin
maksimointi nosti tuon kuvioinnin niin voimakkaaksi, ettC$ OpenCV nC$ki
pelkkC$C$ C$C$rettC6mC$n tiheC$C$ kohinaa. Kun tC$hC$n yhdistettiin meidC$n
sulatus-operaatio, koko ruutu suli yhdeksi ainoaksi giganttiseksi laatikoksi,
joka hylC$ttiin koodin area < (screen_area * 0.90) -sC$C$nnC6llC$. Siksi se ei
lC6ytC$nyt "yhtC$C$n suurta aluetta".
Korjataan tC$mC$ oikeaoppisella konenC$C6llC$
Sen sijaan, ettC$ lisC$C$mme kontrastia, meidC$n pitC$C$ sumentaa (blur) kuvaa
aggressiivisesti! Blurraus kadottaa kaikki pienet yksityiskohdat (kuten
taustan doodlet ja tekstin), mutta jC$ttC$C$ jC$ljelle kC$yttC6liittymC$n
suuret, rakenteelliset massat ja tyhjC$t tilat (kuten piirtC$mC$si oranssin
linjan).
Korvaa layout_parser.py -tiedostossa pelkC$stC$C$n tuo detect_major_frames
-funktio tC$llC$ uudella versiolla:
def detect_major_frames(gray_img):
"""
Etsii ruudun pC$C$alueet blurraamalla yksityiskohdat piiloon.
"""
# 1. Poistettiin equalizeHist!
# 2. Aggressiivinen sumennus: tappaa taustakuvion ja tekstin kohinan
blurred = cv2.GaussianBlur(gray_img, (31, 31), 0)
# 3. EtsitC$C$n reunat sumennetusta kuvasta
edges = cv2.Canny(blurred, 15, 50)
# 4. Kaksivaiheinen sulatus (Morphological Close)
# A) Pystysuunta: YhdistetC$C$n elementit korkeiksi pilareiksi (esim.
chat-lista)
kernel_v = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 200))
closed = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel_v)
# B) Vaakasuunta: YhdistetC$C$n alueet leveyden suunnassa vC$hC$n
kernel_h = cv2.getStructuringElement(cv2.MORPH_RECT, (50, 20))
closed = cv2.morphologyEx(closed, cv2.MORPH_CLOSE, kernel_h)
contours, _ = cv2.findContours(closed, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
frames = []
screen_h, screen_w = gray_img.shape
screen_area = screen_h * screen_w
debug_img = cv2.cvtColor(gray_img, cv2.COLOR_GRAY2BGR)
for c in contours:
x, y, w, h = cv2.boundingRect(c)
area = w * h
# 5. Suodatetaan oikeat alueet:
# PeittC$C$ vC$hintC$C$n 4% mutta alle 95% ruudusta
if area > (screen_area * 0.04) and area < (screen_area * 0.95):
# Vaaditaan myC6s, ettC$ alue on riittC$vC$n korkea (yli 30%
ruudusta)
# jotta esim. ylC$palkit eivC$t sekoita pC$C$jakoa
if h > (screen_h * 0.3):
frames.append({"x": x, "y": y, "w": w, "h": h})
# PiirretC$C$n paksut oranssit boksit!
cv2.rectangle(debug_img, (x, y), (x+w, y+h), (0, 165, 255), 5)
frames.sort(key=lambda f: f["x"])
cv2.imwrite("/tmp/layout_debug.png", debug_img)
print("[*] Tallennettiin debug-kuva laatikoinneista: /tmp/layout_debug.png"
)
return frames
Kokeile!
* PC$ivitC$ koodi.
* Aja python3 layout_parser.py uudelleen.
* Avaa /tmp/layout_debug.png.
Nyt sen pitC$isi osata ignoroida tuo C$rsyttC$vC$ taustakuviointi ja jakaa
ruutu tC$ydellisesti vasempaan listaan ja oikeaan chat-alueeseen. MiltC$
debug-kuva nC$yttC$C$ nyt? Jos siinC$ on selkeC$t kaksi laatikkoa,
pC$C$tteeseen pitC$isi myC6s tulostua vihdoin se siisti, luokiteltu
Markdown-lista!