Diskuze: Porovnání několika pixelů
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Člen
Zobrazeno 21 zpráv z 21.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Nevím zda jsem jediný kdo nechápe na co se ptáš...? Možná proto že nevím (a nehledal jsem to) co je to "gravírovačka". Nicméně z programátorského pohledu nechápu jak (resp. hlavně proč) ukládáš pixely do stringu? A s čím se mají porovnávat?
To je pravda, proč string?
Asi bys to měl blíž popsat - to procházíš nějakou bitmapu ?
A dobrý by byl nějaký konkrétní kód.
Proč string je to jednoduché int "123123" string "123, 123"... vyzkouším to vysvětlit trošku jinak mám obrázek kde jsou černé a bílé pixely získám pozice všech černých pixelu a potom bych potřeboval plochy které budou obsahovat třeba 6x6, 3x3 a 1x1 tzn že se postupně bude posouvat 1x1 poslední pozice 6x6 a pokud v těchto pixelech a na konci vsechny souradnice srovna s zicema černých pixelů a pokud v každé té skupině najde jeden černý pixel tak se odstraní poté se to stejné z opakuje s 3x3 a 1x1 kdy se bude porovnavat s černou a všemi předchozími tzn 6x6... 3x3
asi jste mě stále nepochopili.. černá barva je část která se nebude měnit a bílá část se bude odstraňovat pomocí frézy.. chci aby byla možnost použití různých fréz dle tloušťky "mezery" bíle pixely získávám z bitmap
Bitmap schematic = new Bitmap;
List<string> Pos_blc= new List<string>()
schematic = pic_box.image;
//hledání černých pixelu je uděláno pomocí funkce for
Color pixelColor = myBitmap.GetPixel(50, 50);
if(pixelColor.R <=200 && pixelColor.G <=200 && pixelColor.B <=200 )
{
//tímto způsobem získám bíle pixely včetně tmavších odstínu a zapíšu jako list string
Pos_blc.add(pos_x +","+ pos_y)
}
a teď přichází problém... pokud by se tato funkce ovládala jen pomocí pixelů musel bych použít malý nástroj a gravírování by trvalo dlouho takže bych potřeboval nějakou funkci který by byla schopná najít nějaké společné pixely na tloušťku nástroje viz obrázek..
Řešil bych to asi tak, že bych procházel bitmapu a ve chvíli kdy bych narazil na bílý pixel, prohledal bych jeho okolí abych zjistil jestli tam je další, nebo jestli je osamocený. Pokud by tam byl další tak bych prohledal i jeho okolí a tak pořád dokola, dokud bych nenarazil na černou barvu. Určitě bych to ale nedával do pole stringů, protože s tím se pak nedá rozumě pracovat. Nechal bych to v bitmapě a někam bych připojil informací o tom, jaký nástroj se má kde použít. Nebo by šlo vytvořit nějakou vlastní strukturu, do které by sis ukládal informace získané z bitmapy. V podstatě by tam šlo ukládat jednotlivé "tahy". Tzn. souřadnice počátku, souřadnice konce a typ použitého nástroje. Možností je vždycky celá řada.
Ještě jsem si to prošel a asi to udělám pomocí vertikalnich a horizontálních cest kdyby to vzalo třeba souradnici 1x20 - 40 a našlo by to stejné v dalších osach tzn.. 2x20 - 40 3x20 - 40 atd... dokud by to nenašlo černý pixel až budu mít k dispozici pc tak něco udělám a pochlubim se... jinak ten string jsem změnil na float protože jsem potřeboval desetiny
vyzkoušel jsem napsat program který zjištuje stejné pozice pixelu ve sloupci, ale vypíše se asi 3-5 řádku a zbytek jsou samé nuly nevím proč zkoušel jsem kontrolovat zdroják ale nic jsem nenašel
for (int a = 1; bitmapHeight > a; a++)
{
if (xPos[x] == b)
{
y1[x1] = yPos[x];
x1++;
x++;
}
else if(xPos[x] == (b + 1))
{
y2[x1] = yPos[x];
x++;
x1++;
}
else
{
for(int i = 0; i < y1.Length; i++)
{
for(int j = 0; j < y2.Length; j++)
{
if(y1[i] == y2[j])
{
if(y1[i] > 1)
{
value_lenght++;
value[value_lenght] = y1[i];
}
}
}
}
x1 = 0;
b++;
}
}
string[] result = value.Select(h => h.ToString()).ToArray();
System.IO.File.WriteAllLines("c:\\files.gcode", result );
Pokud jde o rychlost tak bych v žádném případě nepoužíval GetPixel, ale LockBits a pak procházet pixely pomocí pointeru. Vytvářet novou instanci třídy Color pro každý pixel, kterých jsou v běžné bitmapě stovky, bude násobně pomalejší než prostě skočit přes pointer na další pixel (adresu) a dereferencí přečíst příslušné hodnoty RGB.
nemyslím rychlost programu ale rychlost ovládaného stroje...
Dobrý point, ale tady nejsme v low levlu, ale v C# a managed kodu, zmiňovat pointery a dereferenci, je tedy zde dosti mimo mísu.
Tohle je funkce pro převod fotky na stupně šedé, a schválně si to zkus udělat tak že budeš vyzobávat jednotlivé pixely pomocí GetPixel a následně zapisovat pomocí SetPixel. A změř si časy pro nějakou větší fotku a uvidíš co je mimo mísu....
public static void PrevodNaStupneSede(ref Bitmap bitmap)
{
if (bitmap == null)
throw new NullReferenceException();
Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
BitmapData bitmapData = bitmap.LockBits(rect, ImageLockMode.ReadWrite,
PixelFormat.Format32bppArgb);
unsafe
{
byte* pData = (byte)(void)bitmapData.Scan0;
int delka = (bitmapData.Height * bitmapData.Width * 4);
byte* pKonec = pData + delka;
byte b;
while (pData < pKonec)
{
b = (byte)(((11 * ((pData + 2)) + 59 * ((pData + 1)) + 30 *
(*(pData)))) / 100);
*(pData + 3) = 255;
*pData = b;
*(pData + 1) = b;
*(pData + 2) = b;
pData += 4;
}
}
bitmap.UnlockBits(bitmapData);
}
Zrovna v tomhle případě souhlasím s Radkem, přes pointer je to o celý
řád rychlejší než přes GetPixel().
Proto se i v C# celkem běžně pro rychlou práci s bitmapama (kde potřebuješ
řešit jednotlivý pixely) používají pointery přes unsafe, takže
je fuk, jestli jsme v managed kódu nebo ne a mimo mísu to rozhodně není.
Jinak co se detekce týče, jak přesně pak zadáváš vstupy pro to gravírování? Jako seznam bodů a jejich velikostí? Nebo můžeš i zadávat linie?
Jestli je to jen zadávání bodů, tak je to vlastně hledání co největších vepsaných kružnic, to bych asi procházel všechny bílý pixely a zjišťoval, jak velkou kružnici tam můžu udělat, aby pořád ještě pokrývala jen bílou barvu a pak bych asi začal od těch největších a přidal je do seznamu pro gravírování a přepočítal bych ty kružnice, který to ovlivnilo (abys třeba nepálil některý pixely dvakrát).
abyhc řekl pravdu tak programovat jsem se učil z internetu pomocí vyhledávání tagu.. takže moc nevím jak takovou funkci udělat předpokládám že vezmu nějaký pixel a zjistím jakou barvu mají pixely kolem pak do každého směru přidám pixel a udělám to stejné dokud nenarazím na černý pixel... tento nápad se mi líbí ale moje mozková kapacita nedosahuje toho aby jsem program napsal správně
ono asi bude záležet na tom, jakým způsobem se pohybuje gravírovací hlava a jaký tvar a rozměr má gravírovací nástroj. A podle toho, zvolit nejvhodnější způsob detekce.
myslím si že je hloupost předem definovat rozměr nástroje to pak pro to udělám nějakou matiku.. myslím si že nejlepší by bylo aby se pohybovala po rádcích
pokud nemáš definovanou "šířku" nástroje tak nechápu proč detekovat bílé body v okolí (navíc pokud se chceš pohybovat po řádcích)? Nebo ta gravírka si volí nástroje nějak automaticky? Aby Ti mohl někdo pomoct budeš to muset trochu víc popsat, hlavně to jaký potřebuješ ideální výstup. Podle zdejších reakcí asi nejsem jediný, kdo vůbec nechápe co vlastně potřebuješ...
dneska jsem si sedl a dodělal jsem funkci... nakonec jsem to udělal tak že bude jeden nástroj (červená barva v obrázku) která jezdí středem mezery.. teď jen dodělat generování posunu os a program má zařízený kompletní pohyb... zdroják
snad už poslední dotaz... dneska jsem si hrál s programem a zkoušel jsem různá schemata a generovat cesty pro gravirovačku, ale některé cesty jsou přerušené viz. obrázek... jak by jste to řešili ? jediné co mě napadlo je že by to hledalo bílá místa kolem pixelů a snažilo je to dokreslit třeba v okruhu dvacet pixelu... samozřejmě s nějakou logikou aby se program snažil generovat trasy podle předlohy předchozích pixelu..
Zobrazeno 21 zpráv z 21.