Kirjoittaja Aihe: Valokuvan henkilöiden ääriviivat [ratkaistu]  (Luettu 1174 kertaa)

ilkant

  • Käyttäjä
  • Viestejä: 1595
  • Kubuntu
    • Profiili
Minä kokeilin yhtä Pythonin pakettia cv2, jonka metodi divide teki valokuvasta lyijykynäluonnoksen. Ihan hieno. Tuo paketti on tosin opencv, eikä cv2. Google vei tuonne. Noita paketteja löytyi myös cv3, mutta sen sisältö ei ollut näkyvillä. Ja cv13. Jne.

Nyt tarvitsisin pakettia, joka osaisi piirtää ryhmästä ihmisiä ääriviivat. Tarkoitus on sitten numeroida ne hahmot erilliesessä kuvassa ja laittaa nimitiedät listaan. Tällaisia olen nähnyt. Millähän python-paketilla sellaisen ääriviiva-kuvan ihmisjoukosta saisi aikaan?
« Viimeksi muokattu: 03.09.25 - klo:20.38 kirjoittanut ilkant »

nm

  • Käyttäjä
  • Viestejä: 16762
    • Profiili
Vs: Valokuvan henkilöiden ääriviivat
« Vastaus #1 : 03.09.25 - klo:16.12 »
Metan Segment Anything 2 (SAM2) -malli osaa rajata hahmoja ja esineitä kuvista joko automaattisesti tai siten, että käyttäjän tarvitsee vain klikata rajattavia kohteita. Malli pystyy myös seuraamaan valitun hahmon liikettä videossa. SAM2 on vapaasti saatavilla omaan käyttöön, ja mallista on neljä eri kokoista versiota kevyestä raskaampaan.

Käy kokeilemassa netissä toimivaa demoa: https://sam2.metademolab.com/demo

Kuvankäsittelyä varten SAM2-mallin voi kytkeä lisäosan avulla esimerkiksi Gimp-ohjelmaan. En ole kuitenkaan itse kokeillut, miten tämä toimii:
https://github.com/Shriinivas/gimpsegany


Minä kokeilin yhtä Pythonin pakettia cv2, jonka metodi divide teki valokuvasta lyijykynäluonnoksen. Ihan hieno. Tuo paketti on tosin opencv, eikä cv2. Google vei tuonne. Noita paketteja löytyi myös cv3, mutta sen sisältö ei ollut näkyvillä. Ja cv13. Jne.

OpenCV:n nykyinen versio on 4.12.0. Python-moduuli on nimeltään cv2, mutta se seuraa näitä viimeisimpiä julkaistuja versioita:
https://opencv.org/releases/
https://pypi.org/project/opencv-python/
« Viimeksi muokattu: 03.09.25 - klo:16.20 kirjoittanut nm »

ilkant

  • Käyttäjä
  • Viestejä: 1595
  • Kubuntu
    • Profiili
Vs: Valokuvan henkilöiden ääriviivat
« Vastaus #2 : 03.09.25 - klo:19.55 »
Käy kokeilemassa netissä toimivaa demoa: https://sam2.metademolab.com/demo

Kävin kokeilemassa. Ensin Chromium-selain ei toiminut Terms and services -hyväksymisessä. Se ei edennyt minnekään. Kokeilin Firefoxilla ja se toimi. Kuitenkin kun yritin ladata sinne kuvatiedostoa omalta koneeltani, ei mitään tapahtunut. Tiedostonvalitsemiseen asti kyllä toimi. Mutta sinne tiedosto ei havaittavasti mennyt. Kokeilin vaihtaa .jpeg -tyypin .jpg;si eikä se auttanut mitään.

Sitten tuli idea kysyä Chat GPT 5:ltä. Ja se teki python-ohjelman. Mutta kun yritin pipillä asentaa mediapipeä, tuli ilmoitus, ettei sellaista ole. Vielä jää ilmeisesti se SAM, jonka voi lisätä Gimppiin. Tämä kuvarajauskokeilu ei ole nyt mikään pakko saada aikaan. Jos en löydä tapaa tehdä sitä ääriviivaa, niin saa jäädä.

Koodia: [Valitse]
# pip install mediapipe opencv-python numpy

import cv2
import numpy as np
import mediapipe as mp

def person_mask_mediapipe(bgr):
    rgb = cv2.cvtColor(bgr, cv2.COLOR_BGR2RGB)
    seg = mp.solutions.selfie_segmentation.SelfieSegmentation(model_selection=1)
    res = seg.process(rgb)
    seg.close()
    # res.segmentation_mask on [0..1]; ihmiset ~1.0
    m = (res.segmentation_mask > 0.5).astype(np.uint8) * 255
    return m

def mask_to_contours(mask, min_area=200):  # poista pikku-roska
    cnts, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = [c for c in cnts if cv2.contourArea(c) >= min_area]
    return cnts

def draw_outlines_on(target_bgr, contours, color=(255,255,255), thickness=3):
    out = target_bgr.copy()
    # valkoinen viiva + ohut tumma varjo
    cv2.polylines(out, contours, isClosed=True, color=(0,0,0), thickness=thickness+2, lineType=cv2.LINE_AA)
    cv2.polylines(out, contours, isClosed=True, color=color, thickness=thickness, lineType=cv2.LINE_AA)
    return out

# --- käyttö ---
src = cv2.imread("lahtokuva.jpg")            # kuva josta ääriviivat
tgt = cv2.imread("kohdekuva.jpg")            # kuva johon piirretään

mask = person_mask_mediapipe(src)
contours = mask_to_contours(mask)

# skaalaa/siirrä kontuurit kohdekuvaan (esimerkki: sama koko)
scale_x = tgt.shape[1] / src.shape[1]
scale_y = tgt.shape[0] / src.shape[0]
M = np.array([[scale_x, 0, 0],
              [0, scale_y, 0]], dtype=np.float32)
scaled = [cv2.transform(c, M) for c in contours]

out = draw_outlines_on(tgt, scaled, color=(255,255,255), thickness=3)
cv2.imwrite("kohde_outlines.jpg", out)

Toinen Chat GPT 5:n koodi. Sain sen asentumaan, mutta kun ajoin ohjelman, se pysähtyi virheeseen.

Koodia: [Valitse]
torch.AcceleratorError: CUDA error: no kernel image is available for execution on the device
CUDA kernel errors might be asynchronously reported at some other API call, so the stacktrace below might be incorrect.
For debugging consider passing CUDA_LAUNCH_BLOCKING=1
Compile with `TORCH_USE_CUDA_DSA` to enable device-side assertions.

Koodia: [Valitse]
# pip install ultralytics opencv-python numpy

import cv2, numpy as np
from ultralytics import YOLO

# Lataa segmentointimalli (voit valita kevyemmän 'yolov8s-seg.pt')
model = YOLO("yolov8x-seg.pt")

def person_polygons_yolo(bgr):
    res = model.predict(bgr, imgsz=960, conf=0.4, classes=[0])  # class 0 = person
    polys = []
    for r in res:
        if r.masks is None:
            continue
        for m in r.masks.xy:   # list of Nx2 polygon points
            polys.append(np.int32([m]))
    return polys

def draw_polygons_on(target_bgr, polys, color=(255,255,255), thickness=3):
    out = target_bgr.copy()
    cv2.polylines(out, polys, isClosed=True, color=(0,0,0), thickness=thickness+2, lineType=cv2.LINE_AA)
    cv2.polylines(out, polys, isClosed=True, color=color, thickness=thickness, lineType=cv2.LINE_AA)
    return out

src = cv2.imread("lahtokuva.jpg")
tgt = cv2.imread("kohdekuva.jpg")

polys = person_polygons_yolo(src)

# skaalaus kohdekuvan mittaan (tarvittaessa)
sx = tgt.shape[1] / src.shape[1]
sy = tgt.shape[0] / src.shape[0]
M = np.array([[sx, 0, 0],[0, sy, 0]], dtype=np.float32)
polys_scaled = [cv2.transform(p, M) for p in polys]

out = draw_polygons_on(tgt, polys_scaled, color=(255,255,255), thickness=3)
cv2.imwrite("kohde_outlines.jpg", out)

Vielä on mahdollisuus käyttää APIa. En taida kokeilla kun siinä on API-KEY, jota minulla ei varmaan ole.

Koodia: [Valitse]
# pip install requests opencv-python numpy

import requests, cv2, numpy as np

API_KEY = "YOUR_REMOVE_BG_KEY"
with open("lahtokuva.jpg","rb") as f:
    r = requests.post(
        "https://api.remove.bg/v1.0/removebg",
        files={"image_file": f},
        data={"size": "auto"},
        headers={"X-Api-Key": API_KEY},
    )
open("cutout.png","wb").write(r.content)

# Lataa maski alfakanavasta ja tee ääriviivat
img = cv2.imread("cutout.png", cv2.IMREAD_UNCHANGED)
alpha = img[:,:,3]
cnts, _ = cv2.findContours((alpha>0).astype(np.uint8)*255, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

tgt = cv2.imread("kohdekuva.jpg")
# skaalaa kuten aiemmin, piirrä ääriviivat
« Viimeksi muokattu: 03.09.25 - klo:20.16 kirjoittanut ilkant »

ilkant

  • Käyttäjä
  • Viestejä: 1595
  • Kubuntu
    • Profiili
Vs: Valokuvan henkilöiden ääriviivat
« Vastaus #3 : 03.09.25 - klo:20.37 »
Hah. Edistystä tapahtui. Annoin Chat GPT:lle niitä virheilmoituksia kahteen otteeseen. Ja lopulta tuo teki sen, mitä pitkin. Mustavalkokuvan henkilöihin tuli valkoiset ääriviivat. Mutta. Minähän ohjeistin projmptilla ihan liian ylimalkaisesti tehtävän. Kuvassa oli vielä ääriviivojen lisäksi henkilöiden kuvat ja tausta. Ja sitten toinen huono juttu oli, että python-ohjelma ei osannut löytää kaikkia ihmisiä kuvasta.

Tässä vaiheessa merkitsen tämän ratkaistuksi.

Ilmeisesti pitää käsin tehdä ne ääriviivat.

ilkant

  • Käyttäjä
  • Viestejä: 1595
  • Kubuntu
    • Profiili
Vs: Valokuvan henkilöiden ääriviivat [ratkaistu]
« Vastaus #4 : 03.09.25 - klo:23.10 »
Tässä on tämänhetkinen kuva. Siinä on taustat ja naamat poistettu ja hahmot numeroitu. Osa ihmisistä tosin ei ole päässyt mukaan kun Pythonin ultralytics ei ole heitä tunnistanut. Kyllä nyt pitää peukuttaa Chat GPT 5:sta sen kyvykkyydestä. Ehkä keksin vielä keinon, millä loputkin ihmiset saa tuohon kuvaan.

nm

  • Käyttäjä
  • Viestejä: 16762
    • Profiili
Vs: Valokuvan henkilöiden ääriviivat
« Vastaus #5 : 04.09.25 - klo:13.48 »
Kävin kokeilemassa. Ensin Chromium-selain ei toiminut Terms and services -hyväksymisessä. Se ei edennyt minnekään. Kokeilin Firefoxilla ja se toimi. Kuitenkin kun yritin ladata sinne kuvatiedostoa omalta koneeltani, ei mitään tapahtunut. Tiedostonvalitsemiseen asti kyllä toimi. Mutta sinne tiedosto ei havaittavasti mennyt. Kokeilin vaihtaa .jpeg -tyypin .jpg;si eikä se auttanut mitään.

SAM2:n nettidemo taitaa tukea vain videotiedostoja.

Sitten tuli idea kysyä Chat GPT 5:ltä. Ja se teki python-ohjelman. Mutta kun yritin pipillä asentaa mediapipeä, tuli ilmoitus, ettei sellaista ole.

Hmm. Kyllä Mediapipen pitäisi olla saatavilla ainakin Pythonin versioille 3.9 - 3.12. Yrititkö Python 3.13:lla?

Koodia: [Valitse]
pip install mediapipe
Koodia: [Valitse]
Collecting mediapipe
  Downloading mediapipe-0.10.21-cp312-cp312-manylinux_2_28_x86_64.whl.metadata (9.7 kB)
Collecting absl-py (from mediapipe)
  Downloading absl_py-2.3.1-py3-none-any.whl.metadata (3.3 kB)
Requirement already satisfied: attrs>=19.1.0 in ./env-3.12/lib/python3.12/site-packages (from mediapipe) (25.1.0)
Collecting flatbuffers>=2.0 (from mediapipe)
« Viimeksi muokattu: 04.09.25 - klo:13.53 kirjoittanut nm »

ilkant

  • Käyttäjä
  • Viestejä: 1595
  • Kubuntu
    • Profiili
Vs: Valokuvan henkilöiden ääriviivat
« Vastaus #6 : 08.09.25 - klo:00.42 »
Hmm. Kyllä Mediapipen pitäisi olla saatavilla ainakin Pythonin versioille 3.9 - 3.12. Yrititkö Python 3.13:lla?

Pythonilla on versio 3.13.3.

Olen kehittänyt sitä python-ohjelmaa edelleen. Nyt voi valita taustan värin ja myös numeroiden värin. Ohjelma jättää noin 5 hahmoa (ihmistä) tunnistamatta. Helposti voisi koodista vaihtaa myös ääriviivan paksuuden ohuemmaksi/paksummaksi, jos haluaa. Kokeilin sitten henkilöiden tunnistuksen parantamiseksi

model = YOLO("yolo11x-seg.pt")

kahdeksikon sijaan. Ei se silti tunnistanut niitä puuttuvia ihmisiä. Sanoin sitten yhdelle kuvasta kiinnostuneelle, että piirtää itse käsin siihen ne puuttuvat ihmiset. Tuo kokeilu on sinänsä jo ihan ok, mutta ainahan sitä voisi kehittää paremmaksi, jos se tapahtuu kohtuullisilla ponnistuksilla.
« Viimeksi muokattu: 08.09.25 - klo:00.48 kirjoittanut ilkant »