{"id":1199,"date":"2025-11-16T22:13:25","date_gmt":"2025-11-16T20:13:25","guid":{"rendered":"https:\/\/www.pilvikoodari.net\/?p=1199"},"modified":"2025-11-17T08:13:58","modified_gmt":"2025-11-17T06:13:58","slug":"ai-pohjainen-kuvien-analysointi","status":"publish","type":"post","link":"https:\/\/www.pilvikoodari.net\/?p=1199","title":{"rendered":"AI-pohjainen kuvien analysointi"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Olen helppok\u00e4ytt\u00f6isten AI-ratkaisujen puolestapuhuja. Yleens\u00e4 oman mallin kouluttaminen ei ole j\u00e4rkev\u00e4\u00e4 ja mallia ei my\u00f6sk\u00e4\u00e4n v\u00e4ltt\u00e4m\u00e4tt\u00e4 kannata ajaa itse.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Netiss\u00e4 on nimitt\u00e4in palveluita, jotka tarjoavat valmiiksi viimeisteltyj\u00e4 AI-ratkaisuja rajapintojen kautta kenen tahansa k\u00e4ytett\u00e4v\u00e4ksi. Toki pieni maksu n\u00e4ist\u00e4 yleens\u00e4 menee. Etuna on laajat valikoimat valmiita malleja eri tarkoituksiin, helppok\u00e4ytt\u00f6isyys ja nopea k\u00e4ytt\u00f6\u00f6notto.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">T\u00e4ss\u00e4 kokeilussa p\u00e4\u00e4tin tutustua paremmin <a href=\"https:\/\/www.replicate.com\" target=\"_blank\" rel=\"noreferrer noopener\">replicate.com <\/a>-palveluun, joka tarjoaa ison valikoiman valmiita AI-malleja. Palvelua voi k\u00e4ytt\u00e4\u00e4 suoraan rajapintojen kautta, mutta malleja voi my\u00f6s halutessaan ajaa Docker-kontissa.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">P\u00e4\u00e4tin todistaa, ett\u00e4 AI-mallin k\u00e4ytt\u00f6 ohjelmakoodista k\u00e4sin on varsin helppoa. Ja niinh\u00e4n se olikin. Projekti kasvoi lopulta hieman isommaksi kuin olin suunnitellut ja itse AI-osuus olikin loppujen lopuksi hyvin pieni osa kokonaisuudesta.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Joka tapauksessa &#8211; projekti osoitti, ett\u00e4 datan ja teko\u00e4lyn avulla voidaan tuottaa innovatiivisia palveluja varsin helposti.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Projektin l\u00e4ht\u00f6kohdat ja idean muodostuminen <\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">T\u00e4ss\u00e4 koodausprojektissa oli tarkoituksena kehitt\u00e4\u00e4 innovatiivinen, pilvipohjainen ratkaisu, joka hy\u00f6dynt\u00e4\u00e4 valmista teko\u00e4lymallia <a href=\"https:\/\/www.replicate.com\" target=\"_blank\" rel=\"noreferrer noopener\">replicate.com <\/a>-palvelun kautta.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Olen jo aikaisemmin perehtynyt Digitrafficin palveluihin ja jostain syyst\u00e4 Digitrafficin kelikamerat kiinnostavat minua paljon. On mielest\u00e4ni kiehtovaa, ett\u00e4 voin hakea tuoretta kamerakuvaa ymp\u00e4ri Suomen helpon rajapinnan kautta.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Itse miell\u00e4n n\u00e4m\u00e4 kamerat mieless\u00e4ni my\u00f6s &#8221;liikennekameroiksi&#8221; sill\u00e4 ne kuvaavat p\u00e4\u00e4osin maanteit\u00e4 ja kuvissa on yleens\u00e4 vain tie ja mahdollisesti kuvaan sattuneita autoja. On toki ihan mielenkiintoista n\u00e4hd\u00e4 mik\u00e4 keli on ymp\u00e4ri Suomen, mutta ei siit\u00e4 pidemm\u00e4n p\u00e4\u00e4lle innostu.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Liikennem\u00e4\u00e4rien seurantaan on omat palvelunsa ja rajapintansa, eik\u00e4 nyt menn\u00e4 siihen. Liikennem\u00e4\u00e4rien rajapintoja k\u00e4ytettiin edellisess\u00e4 kirjoituksessa <a href=\"https:\/\/www.pilvikoodari.net\/?p=1157\" data-type=\"page\" data-id=\"6\" target=\"_blank\" rel=\"noreferrer noopener\">Kokonaisen j\u00e4rjestelm\u00e4n toteutus AI:lla<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Meill\u00e4 on siis jatkuvasti kuvia tuottava j\u00e4rjestelm\u00e4, mutta kuvat itsess\u00e4\u00e4n eiv\u00e4t ole <strong>yleens\u00e4<\/strong> kovin kiinnostavia. <strong><em>Mit\u00e4p\u00e4 jos valjastetaan AI k\u00e4ym\u00e4\u00e4n kuvia l\u00e4pi ja etsim\u00e4\u00e4n sielt\u00e4 mielenkiintoisia tapahtumia. Itse menemme katsomaan kuvia vain silloin, kun l\u00f6yd\u00f6ksi\u00e4 tulee!<\/em><\/strong><\/p>\n\n\n\n<figure class=\"wp-block-pullquote\"><blockquote><p><strong><em>Mit\u00e4p\u00e4 jos valjastetaan AI k\u00e4ym\u00e4\u00e4n kuvia l\u00e4pi ja etsim\u00e4\u00e4n sielt\u00e4 mielenkiintoisia tapahtumia. Itse menemme katsomaan kuvia vain silloin, kun l\u00f6yd\u00f6ksi\u00e4 tulee!<\/em><\/strong><\/p><\/blockquote><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">J\u00e4rjestelm\u00e4 voisi tarkkailla itsen\u00e4isesti uusia kuvia ja l\u00e4hett\u00e4\u00e4 ilmoituksen, mik\u00e4li kuvissa n\u00e4kyy mielenkiintoista toimintaa. T\u00e4m\u00e4 on sit\u00e4 automaattista tietojen k\u00e4sittely\u00e4 ja t\u00e4ss\u00e4 tapauksessa viel\u00e4p\u00e4 AI-pohjaisesti!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Rajauksena olisi: etsit\u00e4\u00e4n kuvista ihmisi\u00e4 ja el\u00e4imi\u00e4! Niit\u00e4 ei normaalisti n\u00e4y n\u00e4iss\u00e4 kuvissa, koska kamerat on suunnattu maanteille. Jos kuvassa olisi ihminen, kyseess\u00e4 olisi poikkeuksellinen tilanne. Tai jos tielle eksyy vaikkapa hirvi, se vasta onkin mielenkiintoinen tapahtuma!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">T\u00e4ss\u00e4 esimerkki kuvasta, jossa ei pit\u00e4isi normaalitilanteessa koskaan olla ihmisi\u00e4 tai el\u00e4imi\u00e4:<\/p>\n\n\n\n<div class=\"wp-block-media-text is-stacked-on-mobile\"><figure class=\"wp-block-media-text__media\"><img loading=\"lazy\" decoding=\"async\" width=\"533\" height=\"308\" src=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/Screenshot-2025-11-16-at-20.30.24.png\" alt=\"\" class=\"wp-image-1206 size-full\" srcset=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/Screenshot-2025-11-16-at-20.30.24.png 533w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/Screenshot-2025-11-16-at-20.30.24-300x173.png 300w\" sizes=\"auto, (max-width: 533px) 100vw, 533px\" \/><\/figure><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\">Tie 12 Tampere, Santalahdenpuisto <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">P\u00e4iv\u00e4m\u00e4\u00e4r\u00e4:&nbsp;15.11.2025<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Kellonaika:&nbsp;08:51:09<\/p>\n<\/div><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">N\u00e4ill\u00e4 ajatuksilla &#8211; tuumasta toimeen!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Replicate.com palvelu<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Kuten todettua, t\u00e4ss\u00e4 projektissa tarkoituksena ei ole keskitty\u00e4 itse AI-mallin tekemiseen. Muutamaan palveluun tutustuttuani p\u00e4\u00e4dyin <a href=\"https:\/\/replicate.com\/home\" target=\"_blank\" rel=\"noreferrer noopener\">replicate.com<\/a><a href=\"https:\/\/www.replicate.com\" target=\"_blank\" rel=\"noreferrer noopener\"> <\/a>-palvelun sivuilla ja se teki heti minuun vaikutuksen. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Sivusto on mielest\u00e4ni hienosti tuotteistettu, visuaalisesti miellytt\u00e4v\u00e4 ja selke\u00e4. Mallit on esitelty n\u00e4ytt\u00e4v\u00e4sti ja malleja voi testata suoraan sivuston kautta ennen k\u00e4ytt\u00f6\u00f6nottoa.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Muutamia malleja kokeiltuani tulin my\u00f6s siihen tuntumaan, ett\u00e4 palvelussa n\u00e4ytill\u00e4 olevat mallit ovat varsin laadukkaita. Mukana on my\u00f6s tunnetut laajat kielimallit (LLM) kuten <a href=\"https:\/\/replicate.com\/openai\/gpt-5\">OpenAI:n GPT-5<\/a> ja <a href=\"https:\/\/replicate.com\/anthropic\/claude-4.5-sonnet\">Claude Sonnet 4.5.<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Aiemmin olin tutustunut mm. <a href=\"https:\/\/huggingface.co\/\" target=\"_blank\" rel=\"noreferrer noopener\">Hugging Face<\/a> -palveluun, mutta se tuntuu t\u00e4m\u00e4n j\u00e4lkeen varsin alkeelliselta ja sekavalta palvelulta.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Replicateen rekister\u00f6itynyt k\u00e4ytt\u00e4j\u00e4 voi ostaa &#8221;credittej\u00e4&#8221; ja k\u00e4ytt\u00e4\u00e4 niit\u00e4 vastaan palvelun AI-malleja.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Sijoitin ensin viisi dollaria ja se tuntui riitt\u00e4v\u00e4n aika pitk\u00e4ksi aikaa.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Replicate on siis valintani t\u00e4h\u00e4n projektiin!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Mallin valinta<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Mallien selailu replicate.com -palvelussa on helppoa ja mallit on luokiteltu esim. kuva-malleihin, video-malleihin, tekstin k\u00e4sittelyn malleihin jne. Sivustolla on nostettu esiin mielenkiintoisia uutuuksia ja suositeltuja vaihtoehtoja.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Kiinnostukseni kohteena oli siis kuvien analysointiin sopivat mallit. Kokeilin muutamaa mallia sivuston kautta ja aika nopeasti p\u00e4\u00e4dyin kokeilemaan <a href=\"https:\/\/replicate.com\/franz-biz\/yolo-world-xl\" target=\"_blank\" rel=\"noreferrer noopener\">yolo-world-xl<\/a>&nbsp;-mallia. Se on jatkokehitetty versio <a href=\"https:\/\/github.com\/AILab-CVC\/YOLO-World\" target=\"_blank\" rel=\"noreferrer noopener\">YOLO-World<\/a> object detection -mallista. T\u00e4ll\u00e4 voi hakea vapaalla sanalla m\u00e4\u00e4riteltyj\u00e4 kohteita kuvasta. Nyt l\u00f6ytyikin hieno malli t\u00e4h\u00e4n projektiin!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">yolo-world-xl tuntui my\u00f6s toimivan varsin hienosti, kun kokeilin muutamalla testikuvalla. Mallin etuna on, ett\u00e4 se on ns. Open-Vocabulary Object Detection eli sille voi antaa mink\u00e4 tahansa sanallisen kuvauksen ja se yritt\u00e4\u00e4 l\u00f6yt\u00e4\u00e4 sen kuvasta, vaikka kyseist\u00e4 luokkaa ei olisi ollut mukana mallin koulutuksessa. Aika hienoa!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Alla oleva esimerkki kuvaa, miten tarkasti tunnistus toimii.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/Screenshot-2025-11-16-at-20.02.32.png\"><img loading=\"lazy\" decoding=\"async\" width=\"723\" height=\"722\" src=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/Screenshot-2025-11-16-at-20.02.32.png\" alt=\"\" class=\"wp-image-1201\" srcset=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/Screenshot-2025-11-16-at-20.02.32.png 723w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/Screenshot-2025-11-16-at-20.02.32-300x300.png 300w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/Screenshot-2025-11-16-at-20.02.32-150x150.png 150w\" sizes=\"auto, (max-width: 723px) 100vw, 723px\" \/><\/a><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Analysoinnin tuloksena on kuva, mihin on merkitty l\u00f6yd\u00f6kset ja niiden &#8221;todenn\u00e4k\u00f6isyys&#8221;. Lis\u00e4ksi palautuu JSON-muotoinen vastaus, jossa on tarkemmat tiedot tuloksesta.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Mik\u00e4li l\u00f6yd\u00f6ksi\u00e4 ei tullut, palautuu pelkk\u00e4 JSON-vastaus.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Mallille annetaan l\u00e4ht\u00f6tietona<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>analysoitava kuva<\/li>\n\n\n\n<li><em>class_namess<\/em>: etsitt\u00e4v\u00e4t asiat pilkulla eroteltuna, esim. &#8221;cat, dog&#8221;<\/li>\n\n\n\n<li><em>max_num_boxes<\/em>: maksimim\u00e4\u00e4r\u00e4 l\u00f6yd\u00f6ksille (oletus 100)<\/li>\n\n\n\n<li>score_thr: raja-arvo todenn\u00e4k\u00f6isyydelle, mik\u00e4 aiheuttaa l\u00f6yd\u00f6ksen (oletus: 0,05)<\/li>\n\n\n\n<li>nms_thr: kuinka tiukasti p\u00e4\u00e4llekk\u00e4isi\u00e4 havaintoja poistetaan (oletus: 0,5)<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Esimerkki vastauksesta:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"completed_at\": \"2024-06-19T14:31:18.777635Z\",\n  \"created_at\": \"2024-06-19T14:29:47.118000Z\",\n  \"data_removed\": false,\n  \"error\": null,\n  \"id\": \"s0ww45tvxsrgm0cg63ksyqd90w\",\n  \"input\": {\n    \"nms_thr\": 0.5,\n    \"score_thr\": 0.05,\n    \"class_names\": \"dog, eye, tongue, ear, leash, backpack, person, nose\",\n    \"input_media\": \"https:\/\/replicate.delivery\/pbxt\/KOJpWfZmaP6tUv8fqR2n0z3FdBhtytoP5llaecrvvez0p4LE\/dog.jpeg\",\n    \"return_json\": false,\n    \"max_num_boxes\": 100\n  },\n  \"logs\": null,\n  \"metrics\": {\n    \"predict_time\": 1.866912858,\n    \"total_time\": 91.659635\n  },\n  \"output\": {\n    \"media_path\": \"https:\/\/replicate.delivery\/pbxt\/2sNrEronvBZYBle20lmq9tJkBjMPpDcdK0LdT4lxAt0a7EgJA\/output.png\"\n  },\n  \"started_at\": \"2024-06-19T14:31:16.910722Z\",\n  \"status\": \"succeeded\",\n  \"urls\": {\n    \"get\": \"https:\/\/api.replicate.com\/v1\/predictions\/s0ww45tvxsrgm0cg63ksyqd90w\",\n    \"cancel\": \"https:\/\/api.replicate.com\/v1\/predictions\/s0ww45tvxsrgm0cg63ksyqd90w\/cancel\"\n  },\n  \"version\": \"fd1305d3fc19e81540542f51c2530cf8f393e28cc6ff4976337c3e2b75c7c292\"\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Kokeilin viel\u00e4 etsi\u00e4 ihmisi\u00e4 kelikameran kuvasta ja tulos oli hyv\u00e4:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/Screenshot-2025-10-23-at-16.37.52.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"594\" src=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/Screenshot-2025-10-23-at-16.37.52-1024x594.png\" alt=\"\" class=\"wp-image-1203\" srcset=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/Screenshot-2025-10-23-at-16.37.52-1024x594.png 1024w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/Screenshot-2025-10-23-at-16.37.52-300x174.png 300w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/Screenshot-2025-10-23-at-16.37.52-768x446.png 768w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/Screenshot-2025-10-23-at-16.37.52.png 1342w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">T\u00e4m\u00e4 vakuutti minut niin hyvin, ett\u00e4 valinta oli nyt tehty, ei muuta kuin koodaamaan!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Arkkitehtuurin suunnittelu<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">L\u00e4ht\u00f6kohtana oli, ett\u00e4 j\u00e4rjestelm\u00e4 toteutetaan AWS-pilveen serverless-ratkaisuna. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Koodaus tehd\u00e4\u00e4n Copilotin avulla tehokkaasti ja nopeasti.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Julkaisu pilveen tehd\u00e4\u00e4n AWS CDK:lla (Infrastructure as Code).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Frontend tulisi olemaan varsin kevyt. P\u00e4\u00e4paino olisi autonomisella pilviratkaisulla joka toimii itsen\u00e4isesti:  analysoi kuvia ja l\u00e4hett\u00e4\u00e4 minulle s\u00e4hk\u00f6postia jos kuvissa n\u00e4kyy ihmisi\u00e4 tai el\u00e4imi\u00e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Prosessointi voisi menn\u00e4 suunnilleen n\u00e4in:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Hae kameroiden tiedot Digitrafficilta<\/li>\n\n\n\n<li>Suodata kameralistaus ja ota mukaan vain Tampereen alueen kamerat<\/li>\n\n\n\n<li>Nouda kunkin kameran uusin kuva ja tallenna se pilveen<\/li>\n\n\n\n<li>Aja uusillle kuville analysointi replicate.com palvelussa<\/li>\n\n\n\n<li> Tallenna tulokset tietokantaan ja mahdollinen tuloskuva pilveen<\/li>\n\n\n\n<li>Jos tuli l\u00f6yd\u00f6ksi\u00e4, l\u00e4het\u00e4 h\u00e4lytys s\u00e4hk\u00f6postilla<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">N\u00e4ill\u00e4 l\u00e4ht\u00f6tiedoilla aloin tekem\u00e4\u00e4n j\u00e4rjestelm\u00e4n suunnittelua Github Copilotn kanssa. Copilot ehdotti ett\u00e4 tehd\u00e4\u00e4n oikein ADR-pohjaisesti. ADR eli Architecture Decision Record on lyhyt dokumentti, johon kirjataan yksitt\u00e4inen t\u00e4rke\u00e4 arkkitehtuurip\u00e4\u00e4t\u00f6s, sen perustelut ja seuraukset.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">ADR dokumentteja syntyi lopulta suunnittelun tuloksena 16 kappaletta:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>0001-data-sources-and-analytics.md<\/strong><\/li>\n\n\n\n<li><strong>0002-frontend-access-model.md<\/strong><\/li>\n\n\n\n<li><strong>0003-analysis-model.md<\/strong><\/li>\n\n\n\n<li><strong>0004-image-storage.md<\/strong><\/li>\n\n\n\n<li><strong>0005-dynamodb-schema.md<\/strong><\/li>\n\n\n\n<li><strong>0006-ingest-workflow.md<\/strong><\/li>\n\n\n\n<li><strong>0007-rest-api.md<\/strong><\/li>\n\n\n\n<li><strong>0008-secrets-and-config.md<\/strong><\/li>\n\n\n\n<li><strong>0009-alerting-strategy.md<\/strong><\/li>\n\n\n\n<li><strong>0010-observability-and-logging.md<\/strong><\/li>\n\n\n\n<li><strong>0011-ci-cd-strategy.md<\/strong><\/li>\n\n\n\n<li><strong>0012-naming-conventions.md<\/strong><\/li>\n\n\n\n<li><strong>0013-data-lifecycle.md<\/strong><\/li>\n\n\n\n<li><strong>0014-frontend-architecture.md<\/strong><\/li>\n\n\n\n<li><strong>0015-security-and-identity.md<\/strong><\/li>\n\n\n\n<li><strong>0016-cost-management.md<\/strong><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">N\u00e4m\u00e4 dokumentit l\u00f6ytyv\u00e4t projektin Github-reposta, johon on linkki t\u00e4m\u00e4n kirjoituksen lopussa.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Copilot huomioi hienosti mm. datan s\u00e4ilytysajat.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ensimm\u00e4inen Copilotin tuottama ratkaisuehdotus k\u00e4ytti analysointiprosessiin AWS:n Step Functions -toimintoa. Ehdin jo toteuttaa ratkaisun Step Funktion -pohjaisesti, mutta kustannusten vuoksi pyysin Copilottia tekem\u00e4n halvemman Lambda-pohjaisen ratkaisun.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Arkkitehtuuri<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Oheisessa kuvassa n\u00e4kyy lopullinen arkkitehtuuri. Kaikki komponentit asennetaan AWS CDK:lla. Ainoastaan h\u00e4lytyksen vastaanottajien s\u00e4hk\u00f6postiosoitteet ja replicate.com API key asetetaan AWS pilveen k\u00e4sin.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><a href=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/tca.drawio-2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"736\" src=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/tca.drawio-2-1024x736.png\" alt=\"\" class=\"wp-image-1227\" srcset=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/tca.drawio-2-1024x736.png 1024w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/tca.drawio-2-300x216.png 300w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/tca.drawio-2-768x552.png 768w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/tca.drawio-2.png 1141w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">Prosessin k\u00e4ynnist\u00e4\u00e4 EventBridge ajastus, kerran tunnissa ajalla 9.00-16.00. Uusia kuvia olisi saatavilla useamminkin, mutta kustannusten rajoittamiseksi ajastus s\u00e4\u00e4dettiin t\u00e4llaiseksi.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">FetchCameras Labda-funktio hakee kameratiedot, suodattaa niist\u00e4 vain oleelliset ja puskee latausjonoon eventin.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Latausjonoa k\u00e4sittelee latausfunktio, joka lataa kameran uusimman kuvan, tallentaa sen S3 buckettiin ja l\u00e4hett\u00e4\u00e4 eventin analysointijonoon.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Analysointijonosta teht\u00e4vi\u00e4 ottaa kuvien analysointia tekev\u00e4 lambda-funktio, joka l\u00e4hett\u00e4\u00e4 kuvan Replicate.com palvelussa ajettavaan analysointipalveluun. API key saadaan AWS Secrets Managerilta. Tulos tallennetaan DynamoDB tietokantaan jaa mik\u00e4li Replicate palautti kuvan, se tallennetaan prosessoitujen kuvien S3 buckettiin. Samalla l\u00e4hetet\u00e4\u00e4n tuloksesta tieto EventBridgelle. EventBridge kutsuu h\u00e4lytyksen l\u00e4hetys -funktiota, jos tuloksessa oli l\u00f6yd\u00f6ksi\u00e4.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">H\u00e4lytyksen l\u00e4hetys -funktio l\u00e4hett\u00e4\u00e4 s\u00e4hk\u00f6postia SNS palvelun kautta. Viestiss\u00e4 on havainnon tiedot ja linkki tuloskuvaan. Linkki on presigned linkki kuvaan ja toimii vain tunnin ajan.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Yksinkertaisella frontend-sovelluksella voi selailla havaintoja, valitsemalla kamera-aseman ja p\u00e4iv\u00e4m\u00e4\u00e4r\u00e4n. Frontissa voi my\u00f6s listata kaikki tietyn p\u00e4iv\u00e4m\u00e4\u00e4r\u00e4n l\u00f6yd\u00f6kset.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Frontendi\u00e4 varten on rakennettu yksinkertaisia REST-rajapintoja, jotka tarjoillaan API Gatewayn kautta. API Gateway toteuttaa my\u00f6s tarvittavat rajoitukset, jotta rajapintoja ei voi kutsua t\u00e4ysin rajattomasti ja aiheuttaa suuria kustannuksia.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Jokaisella SQS-jonolla on my\u00f6s ep\u00e4onnistuneita ajoja varten DLQ-jono, johon laitetaan eventit joiden k\u00e4sittely ei onnistunut.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Toteutus ja vianselvitys Copilotin avulla<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Toteutus eteni luonnollisella tavalla: prosessin kukin vaihe toteutettiin kun edellinen oli valmis. Valmistunutta osaa pystyi testaamaan k\u00e4ynnist\u00e4m\u00e4ll\u00e4 ajon manuaalisesti ja seuraamalla Cloudwatch-lokeja ja jonojen tilannetta.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Copilot noudatti ADR-dokumenteissa annettuja suunnitteluperiaatteita. Copilotin ohjetiedostossa <em>copilot-instructions.md<\/em> luki yksinkertaisesti n\u00e4in:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>use adr files as instructions when implementing code: \/docs\/adr<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">DLQ jonoihin kertyi jossain vaiheessa totutusta eventtej\u00e4 ja se kertoi siit\u00e4 ett\u00e4 eventtien k\u00e4sittely oli ep\u00e4onnistunut. Tilanteen sai helposti selvitelty\u00e4 VS Codesta k\u00e4sin, Github Copilotin avulla. Copilot selvitteli tilannetta pilvest\u00e4 ajamalla aws:n komentorivi-komentoja ja korjasi koodin sen perusteella.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Koko toteutus tehtiin siis Copilotin avulla, ns. Vibe-koodauksella.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Frontend<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Frontend toteutettin l\u00e4hinn\u00e4 testauksen tueksi. Siin\u00e4 on l\u00e4hinn\u00e4 yksinkertaiset hakutoiminnot kuvien hakuun ja havaintojen katselu listamuodossa.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/Screenshot-2025-11-16-at-21.59.51.png\"><img loading=\"lazy\" decoding=\"async\" width=\"899\" height=\"808\" src=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/Screenshot-2025-11-16-at-21.59.51.png\" alt=\"\" class=\"wp-image-1219\" srcset=\"https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/Screenshot-2025-11-16-at-21.59.51.png 899w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/Screenshot-2025-11-16-at-21.59.51-300x270.png 300w, https:\/\/www.pilvikoodari.net\/wp-content\/uploads\/2025\/11\/Screenshot-2025-11-16-at-21.59.51-768x690.png 768w\" sizes=\"auto, (max-width: 899px) 100vw, 899px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Yhteenveto<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Projekti oli hyv\u00e4 osoitus teko\u00e4lypohjaisesta kehityksest\u00e4: koodaus tehtiin t\u00e4ysin Copilotin avulla. Huolellinen suunnittelu, prosessin toteutus paloissa, jatkuva testaus, vikojen korjaus Copilotilla. <br><br>Copilot osasi rakentaa AWS-infran t\u00e4ydellisesti AWS CDK:lla.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Event-driven arkkitehtuuri oli t\u00e4ss\u00e4 k\u00e4ytt\u00f6tapauksessa loistava valinta. Kuvien analysointi kest\u00e4\u00e4 jonkin aikaa ja kuvat voidaan l\u00e4hett\u00e4\u00e4 jonosta analysoitavaksi hallitusti.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Replicate.com integraatio oli varsin yksinkertainen, k\u00e4yt\u00e4nn\u00f6ss\u00e4 HTTP kutsu Lambda-funktiosta.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">J\u00e4\u00e4n odottelemaan s\u00e4hk\u00f6postia mielenkiintoisista tapahtumista tien p\u00e4\u00e4ll\u00e4!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Github repository: <a href=\"https:\/\/github.com\/anttirauhala\/traffic-cam-analyzer\">https:\/\/github.com\/anttirauhala\/traffic-cam-analyzer<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Olen helppok\u00e4ytt\u00f6isten AI-ratkaisujen puolestapuhuja. Yleens\u00e4 oman mallin kouluttaminen ei ole j\u00e4rkev\u00e4\u00e4 ja mallia ei my\u00f6sk\u00e4\u00e4n v\u00e4ltt\u00e4m\u00e4tt\u00e4 kannata ajaa itse. Netiss\u00e4 on nimitt\u00e4in palveluita, jotka tarjoavat valmiiksi viimeisteltyj\u00e4 AI-ratkaisuja rajapintojen kautta kenen tahansa k\u00e4ytett\u00e4v\u00e4ksi. Toki pieni maksu n\u00e4ist\u00e4 yleens\u00e4 menee. Etuna on laajat valikoimat valmiita malleja eri tarkoituksiin, helppok\u00e4ytt\u00f6isyys ja nopea k\u00e4ytt\u00f6\u00f6notto. T\u00e4ss\u00e4 kokeilussa p\u00e4\u00e4tin tutustua &#8230; <a title=\"AI-pohjainen kuvien analysointi\" class=\"read-more\" href=\"https:\/\/www.pilvikoodari.net\/?p=1199\" aria-label=\"Lue lis\u00e4\u00e4 aiheesta AI-pohjainen kuvien analysointi\">Lue lis\u00e4\u00e4<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26,25,9,16,10,5,28],"tags":[],"class_list":["post-1199","post","type-post","status-publish","format-standard","hentry","category-ai","category-arkkitehtuuri","category-avoin-data","category-aws","category-json","category-pilvialustat","category-serverless"],"_links":{"self":[{"href":"https:\/\/www.pilvikoodari.net\/index.php?rest_route=\/wp\/v2\/posts\/1199","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pilvikoodari.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pilvikoodari.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pilvikoodari.net\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pilvikoodari.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1199"}],"version-history":[{"count":22,"href":"https:\/\/www.pilvikoodari.net\/index.php?rest_route=\/wp\/v2\/posts\/1199\/revisions"}],"predecessor-version":[{"id":1228,"href":"https:\/\/www.pilvikoodari.net\/index.php?rest_route=\/wp\/v2\/posts\/1199\/revisions\/1228"}],"wp:attachment":[{"href":"https:\/\/www.pilvikoodari.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1199"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pilvikoodari.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1199"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pilvikoodari.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1199"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}