[C#/Algemeen] Foto collage in een bepaalde vorm maken

Pagina: 1
Acties:

Vraag


Acties:
  • +1 Henk 'm!

  • ? ?
  • Registratie: Mei 2007
  • Niet online
Foto zegt alles:
Afbeeldingslocatie: http://www.shapecollage.com/collages/collage-heart-2.jpg

Hoe zou ik dit best kunnen maken (met C# Forms)?

Ik zou een PNG bestand met daarin een zwart wit afbeelding van een hart gebruiken als "shape". De detectie van waar er overal foto's moeten staan zou ik doen door te kijken of de locatie zwart is. Enerzijds door een raster te maken (dan zou ik vaste afstanden gebruiken, die misschien niet goed uitkomen aan de rand. Anderzijds door een variabel raster dat telkens horiztonaal en verticaal het midden berekend en dan kijkt hoeveel foto's er tussen kunnen.

Verder roteer ik de afbeeldingen willekeurig. Tot zover kan ik het wel doen en maakte ik al iets. Maar als je naar de foto hierboven kijkt, is er meer aan de hand. de foto's aan de schuine linkerkant zijn bv. zo gedraaid dat ze de lijn meevolgen. Hoe zou ik dat kunnen implementeren? Of zijn er andere oplossingen om zo'n taak aan te pakken?

Hier gaat het over een hart vorm, in de praktijk ga ik het enkel voor dit gebruiken. Oplossingen mogen echter algemeen zijn. Graag zelfs.

Alle reacties


Acties:
  • 0 Henk 'm!

  • Ventieldopje
  • Registratie: December 2005
  • Laatst online: 19:53

Ventieldopje

I'm not your pal, mate!

Daarbij wil je denk ik ook zorgen dat er geen gaten in vallen én dat iedere foto voor minstens x% zichtbaar is. Ben benieuwd naar eventuele oplossingen van mensen die ervaring hebben met dit soort dingetjes, interessant :)

www.maartendeboer.net
1D X | 5Ds | Zeiss Milvus 25, 50, 85 f/1.4 | Zeiss Otus 55 f/1.4 | Canon 200 f/1.8 | Canon 200 f/2 | Canon 300 f/2.8


Acties:
  • 0 Henk 'm!

  • ? ?
  • Registratie: Mei 2007
  • Niet online
Ja precies, ik vond er niet zo veel over, of zocht op de verkeerde zaken.
Anyway, ik heb wel iets werkende gemaakt ondertussen, met uiteindelijk een redelijk goed resultaat. Post het morgenvroeg.

Acties:
  • 0 Henk 'm!

  • ? ?
  • Registratie: Mei 2007
  • Niet online
Door de commerciele software gegenereerd:

Afbeeldingslocatie: http://i.imgur.com/ooCWVsk.jpg

Door mijn programma gegenereerd:

Afbeeldingslocatie: http://i.imgur.com/iqO5ssl.jpg

Ik vind mijn resultaat beter!
Uiteindelijk heb ik het niet ingewikkeld gemaakt. Per x lijnen scannen op "zwart" zowel horizontaal als verticaal. Telkens de punten opslaan. Vervolgens de set punten willekeurig shufflen en voor elk punt een willekeurige foto kiezen. Een witte rand toevoegen aan de foto en de foto willekeurig (alweer) roteren van -15 tot +15 graden. En deze dan gewoon plaatsen op het punt. (ik plaatste de foto's telkens met de hoek linksboven op het punt, waardoor de gehele afbeeldingen naar links opschuift, je zou het zo kunnen doen dat het midden van de afbeelding op het punt komt). Zolang er punten zijn, worden er foto's geplaatst, het kan dus zijn dat er dubbels in zitten, voor mij geen issue.

Het werkt en ik ben blij. Het is vooral een kwestie van een groot genoeg sjabloon te nemen en eventueel vervolgens het resultaat te verkleinen. Ik heb er een commandline versie van gemaakt "collage.exe" die alle afbeeldigen in de huidige directory neemt en dan deze output geeft.

[ Voor 6% gewijzigd door ? ? op 07-06-2016 19:42 ]


Acties:
  • 0 Henk 'm!

  • Ventieldopje
  • Registratie: December 2005
  • Laatst online: 19:53

Ventieldopje

I'm not your pal, mate!

Ziet er goed uit, mooi gevuld! Je zou nog wat meer randomness kunnen geven aan de rotatie of het af laten hangen van de X / Y positie (X > midden dan meer CW roteren, X < midden dan meer CCW roteren).

Kun je misschien een stukje voorbeeld code plaatsen hoe je scant op zwart? Ben wel benieuwd hoe je dit hebt aangepakt.

www.maartendeboer.net
1D X | 5Ds | Zeiss Milvus 25, 50, 85 f/1.4 | Zeiss Otus 55 f/1.4 | Canon 200 f/1.8 | Canon 200 f/2 | Canon 300 f/2.8


Acties:
  • 0 Henk 'm!

  • ? ?
  • Registratie: Mei 2007
  • Niet online
Afbeeldingslocatie: http://i.imgur.com/LUPrE9x.jpg

ying-yang ! de cirkel van de shape van het ying yang logo is wel te dun, ik detecteer maar elke 50px een mogelijke zwart, vandaar dat de lijn niet volledig is. leiuk he!

Hoe ik detecteer waar er een foto mag komen: (mijn png shape is zwart/wit)
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int margin = 50;
List<Point> points = new List<Point>();
Bitmap b = (Bitmap)Image.FromFile("shape.png");
                Graphics g = Graphics.FromImage(b);

                for (int y = 0; y < b.Height; y++)
                {
                    for (int x = 0; x < b.Width; x++)
                    {
                        Point current = new Point(x, y);
                        Color color = b.GetPixel(x, y);
                        if (color.R == 0 && color.G == 0 && color.B == 0)
                        {
                            if (current.X % margin == 0 && current.Y % margin == 0)
                            {
                                points.Add(current);
                            }
                        }
                    }
                }


dat is echt de meest basic manier die je kan bedenken, maar soit het werkt :)

[ Voor 3% gewijzigd door ? ? op 07-06-2016 20:24 ]


Acties:
  • 0 Henk 'm!

  • Daos
  • Registratie: Oktober 2004
  • Niet online
Ziet er erg goed uit. En dat maak jij in een paar uurtjes?

Acties:
  • 0 Henk 'm!

  • Ventieldopje
  • Registratie: December 2005
  • Laatst online: 19:53

Ventieldopje

I'm not your pal, mate!

? ? schreef op dinsdag 07 juni 2016 @ 20:21:
[afbeelding]

ying-yang ! de cirkel van de shape van het ying yang logo is wel te dun, ik detecteer maar elke 50px een mogelijke zwart, vandaar dat de lijn niet volledig is. leiuk he!

Hoe ik detecteer waar er een foto mag komen: (mijn png shape is zwart/wit)
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int margin = 50;
List<Point> points = new List<Point>();
Bitmap b = (Bitmap)Image.FromFile("shape.png");
                Graphics g = Graphics.FromImage(b);

                for (int y = 0; y < b.Height; y++)
                {
                    for (int x = 0; x < b.Width; x++)
                    {
                        Point current = new Point(x, y);
                        Color color = b.GetPixel(x, y);
                        if (color.R == 0 && color.G == 0 && color.B == 0)
                        {
                            if (current.X % margin == 0 && current.Y % margin == 0)
                            {
                                points.Add(current);
                            }
                        }
                    }
                }


dat is echt de meest basic manier die je kan bedenken, maar soit het werkt :)
Simpel maar doeltreffend blijkbaar, netjes!

Klein dingetje: eigenlijk lees je nu nog steeds elke pixel uit en bepaal je daarna of deze binnen de marge valt. Zou je niet beter gewoon in de for loop al kunnen skippen? Zo hoef je niet onnodig veel pixels uit te lezen.

www.maartendeboer.net
1D X | 5Ds | Zeiss Milvus 25, 50, 85 f/1.4 | Zeiss Otus 55 f/1.4 | Canon 200 f/1.8 | Canon 200 f/2 | Canon 300 f/2.8


Acties:
  • 0 Henk 'm!

  • Daos
  • Registratie: Oktober 2004
  • Niet online
Hij bedoelt iets als x of y += margin ipv x++ of y++. Dan heb je die hele if (current.X % margin == 0 niet meer nodig en het gaat nog sneller ook.

Die andere if kan je misschien leesbaarder maken door color == Color.Black te gebruiken. Voor snelheid maakt dat niet veel uit.

Acties:
  • 0 Henk 'm!

  • Ventieldopje
  • Registratie: December 2005
  • Laatst online: 19:53

Ventieldopje

I'm not your pal, mate!

Daos schreef op dinsdag 07 juni 2016 @ 21:04:
Hij bedoelt iets als x of y += margin ipv x++ of y++. Dan heb je die hele if (current.X % margin == 0 niet meer nodig en het gaat nog sneller ook.

Die andere if kan je misschien leesbaarder maken door color == Color.Black te gebruiken. Voor snelheid maakt dat niet veel uit.
Dat is inderdaad wat ik bedoel :) Color.Black is inderdaad een stuk beter leesbaar. Je kan dit ook heel simpel aanpassen om transparante afbeeldingen te ondersteunen met Color.A :)

www.maartendeboer.net
1D X | 5Ds | Zeiss Milvus 25, 50, 85 f/1.4 | Zeiss Otus 55 f/1.4 | Canon 200 f/1.8 | Canon 200 f/2 | Canon 300 f/2.8


Acties:
  • 0 Henk 'm!

  • ? ?
  • Registratie: Mei 2007
  • Niet online
Ik heb dit maandagavond tijdens het tv-kijken al liggende in de zetel gemaakt op (+-) een uurtje. Dit stelt niks voor. Een werkend pakketje maken dat altijd werkt, met validaties, exceptions, inputs enz is wat meer werk...


Color.Black wilde hij niet, met de RGB wel. (ik denk dat het door het alpha channel in de png kwam).

De margin en de modulo zijn pas na edits gekomen. Ik had eerst de bedoeling om te kijken of er 'in de buurt' al een point gevonden was om dan die regio over te slaan. Maar dat was mij te veel werk om het zowel horizontaal als verticaal te gaan zoeken. Uiteindelijk duurt het voor 1000x1000 pixels maar een seconde of 2-3 en ik heb $75 uitgespaard.

[ Voor 10% gewijzigd door ? ? op 08-06-2016 10:41 ]


Acties:
  • 0 Henk 'm!

  • epic007
  • Registratie: Februari 2004
  • Laatst online: 07-10 10:46
Voor een beetje meer performance kan je nog naar de LockBits method kijen (GetPixel is traag).

https://msdn.microsoft.co...y/5ey6h79d(v=vs.110).aspx

Via de BitmapData kan je je bitmap dan als array benaderen.
Pagina: 1