FILTRES ET MANIPULATION D'IMAGES EN UTILISANT LOCKBITS ET DES POINTEURS
cs_yoannd
Messages postés305Date d'inscriptionlundi 7 janvier 2002StatutMembreDernière intervention10 août 2011
-
9 déc. 2004 à 18:47
billegate2006
Messages postés2Date d'inscriptionmercredi 17 janvier 2007StatutMembreDernière intervention 1 avril 2008
-
1 avril 2008 à 16:31
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.
billegate2006
Messages postés2Date d'inscriptionmercredi 17 janvier 2007StatutMembreDernière intervention 1 avril 2008 1 avril 2008 à 16:31
Bonjour,
Je veux juste vous poser une question concernant le traitement d'images, bon je veux mettre une bar de zoom sur une image mais il faut quelle soit transparente comme la boussole du google earth, merci de votre reponse.
phoenikz
Messages postés2Date d'inscriptionmardi 8 janvier 2008StatutMembreDernière intervention17 avril 2008 5 mars 2008 à 08:37
J'ai réalisé un programme de traitement d'image à partir d'une webcam et ton code m'a énormément aidé pour passer en noir et blanc et compté les pixels de certaines couleurs, bref un grand merci (enfin bon là j'ai 4 ans de retard mais c'est pas grave)
olixelle
Messages postés506Date d'inscriptionvendredi 30 juillet 2004StatutMembreDernière intervention 3 mars 20082 13 déc. 2007 à 13:04
Salut,
je ne connaissais le mode unsage qu'en théorie, j'en ai eu besoin récement donc je me suis très largement inspiré de ton code pour comprendre le principe et le mettre en application donc merci :)
Remarque: Si vous souahitez gérer la transparence des png, passez en Format32bppARgb et remplacez les 3 par des 4 lors de la copie des pixels (une constante aurait été bienvenue)
en tout cas merci :)
farias46
Messages postés9Date d'inscriptionlundi 29 janvier 2007StatutMembreDernière intervention14 octobre 2008 13 févr. 2007 à 10:37
Monstrueusement efficace !!! J'ai commencé le C# il y a 2 semaines environ et j'ai été très déçu par les performances de celui-ci sur les traitements d'images. En effet j'utilisais la méthode "managed" c'est-à-dire avec les GetPixel et SetPixel. J'arrivais à plus de 14sec pour parcourir une image de 800x600... celà uniquement pour passer celle-ci en négatif!
Avec le mode "unsafe", sur une belle image de la lune avec une petite résolution de 5900x3100 siouplé :-) tous mes filtres prennent maxi 3sec !
Un grand merci à toi pour ce joli code qui m'a fait découvrir la puissance des pointeurs ;-)!
Equinox84
Messages postés63Date d'inscriptionlundi 2 février 2004StatutMembreDernière intervention19 mai 2010 21 juil. 2006 à 10:33
Salut !
Merci pour ton code, il m'a permis d'inverser la couleur de mes graphiques avant l'impression, c'est tres pratique pour économiser le noir !
cs_Warny
Messages postés473Date d'inscriptionmercredi 7 août 2002StatutMembreDernière intervention10 juin 2015 26 mars 2006 à 19:20
Salut à nouveau,
Je me suis inspiré de ton code pour optimiser une déformation d'image (pour faire de l'assemblage horizontal de photo). C'est vrai que c'est nettement plus efficace. Merci beaucoup.
cs_Warny
Messages postés473Date d'inscriptionmercredi 7 août 2002StatutMembreDernière intervention10 juin 2015 26 mars 2006 à 18:00
pour le fonction(i++) et le fonction(++i) le dotnet le compile en...
fonction(i); i = i+1;
et
i=i+1; fonction(i);
respectivement,
donc pour la vitesse, j'ai un doute ;)
kamal101
Messages postés12Date d'inscriptionsamedi 24 janvier 2004StatutMembreDernière intervention22 mars 2007 17 nov. 2005 à 21:44
Est-ce qu'il y a quelqu'un qui sait comment faire en c# la reconnaissance de forme. Je veux trouver des mini-cercles ronds dans une image et les mettre par exemple en noir. Est-ce qu'il y a une librairie pour ça ?
li9
Messages postés57Date d'inscriptionlundi 23 février 2004StatutMembreDernière intervention11 septembre 20081 11 déc. 2004 à 09:41
Salut galinace,
on peut aussi utiliser les fonction "GetPixel()" et "SetPixel()" de la classe Bitmap pour travailler les pixels.
mais ces méthodes sont "très" lentes par rapport à l'utilisation de pointeurs.
Sur MSDN il y a un article interressant là dessus.
l'auteur y écrit qu'en Managed Code (getpixel,setpixel) son filtre Grayscale s'applique en 14sec. (enormement long mdr) , en Unmanaged (pointeurs) : 0.52sec ; )
par contre je vois pas trop ce que tu as fais pour ton test entre Managed et Unmanaged , tu extraits ton bitmap de 2 manieres differente et tu lui appliques mon filtre ? o_o
Sinon mon avis général sur la question c'est que l'étude des pointeurs va me permettre beaucoup de choses impossible à faire en managed code ^^"
wallou
++
cs_galinace
Messages postés2Date d'inscriptionmardi 15 avril 2003StatutMembreDernière intervention11 décembre 2004 11 déc. 2004 à 00:53
Re ....
Je viens de réaliser quelques tests entre ta methode et celle consistant à extraire le graphics du bitmap et travailler directement dessus.
Je me suis permis de modifier un peu ton source afin de laisser la possibilité d'importer une image et par suite remplacer celle par défaut. J'importe une bitmap de taille importante (105 Mo) afin de voir les temps de calculs et la mémoire prise (je suis sur un XP2000+ à 512 DDR).
L'application d'un filtre selon ta methode prend environ 6 à 7 secondes à pleine puissance (je parle ici de travail sans effet mémoire pour la possibilité d'annulation afin de ne pas être inflencé par des éventuel swappages).
La même opération effectuée sur une bitmap par extraction du graphics prends exactement le même temps.
Tout ceci pour pauser la question de l'utilité du mode "unsafe". C'est effectivement une question qui me tracasse pas mal car d'une part, le mode managé permet une certaine "sécurité" du code mais est sensé ralentir quelque peut l'exécution. Malheureusement pour moi, chaque exemple que je peux tester ne me permet pas réellement de trancher sur un mode plutôt que l'autre.
Pourrais tu m'éclarrer sur ton choix (travail en mode unsafe) et ton avis général sur la question ???
D'avance encore merci
cs_galinace
Messages postés2Date d'inscriptionmardi 15 avril 2003StatutMembreDernière intervention11 décembre 2004 11 déc. 2004 à 00:15
Bonjour,
Je viens de lire ton poste et ta methode me parrait effectivement intéressante.
J'aurais aimé avoir une sorte de comparatif ou tout du moins d'ordre d'idée concernant la différence de rapidité d'exécution entre le principe que tu décris (parcourt par pointeur etc) et le fait de rester en mode managé et dessiner la bitmap en passant par un objet "graphics".
Effectivement je ne parle pas là de modification de luminosité ou autre mais bien de dessin à proprement parler d'une bitmap. Je sais que ce n'est pas directement le sujet mais un rapport tout de même étroit m'a poussé a écrire ce poste.
Merci d'avance pour ta réponse
cs_yoannd
Messages postés305Date d'inscriptionlundi 7 janvier 2002StatutMembreDernière intervention10 août 20117 10 déc. 2004 à 09:32
Putain là ouais, ca marche, et c'est nikel !
tu viens de donner pas mal de valeur à ta source là, d'un coup ! ben bravo, je trouve ca extra !
li9
Messages postés57Date d'inscriptionlundi 23 février 2004StatutMembreDernière intervention11 septembre 20081 9 déc. 2004 à 21:18
Merci pour ton commentaire.
Effectivement , y avait quelques fautes mdr ....
J'ai tout corrigé (je pense .... ) et j'ai rajouté un zip avec quelques filtres supplémentaires pour me faire pardonner v( ^_^ )v .
J'ai voulu faire le chaud et tout taper de tête en postant ma source , c'est à cause de ça qu'y avait autant de fautes ....j'aurais dû faire un vieux copier/coller xD
C'est vrai que j'aurais dû parler des namespaces ,
Je m'en excuse !!
Pour "++i" ou "i++" t'as peut être raison, je pensait avoir vu ça dans la version de msdn fournit dans vs.net ... à vérifier ...
et pour la déclar. du pointeur moi les 2 passent niquel o_O , mais je me sert que de "(byte*)(void*)scan0"
Réessayes avec la source de mon zip. : /
on sait jamais ...
Ciao
cs_yoannd
Messages postés305Date d'inscriptionlundi 7 janvier 2002StatutMembreDernière intervention10 août 20117 9 déc. 2004 à 18:52
Ha oui, dernier truc, tu écris ceci dans ton code:
byte* p = (byte*)(void*)scan0;
//on peut aussi écrire "byte* p = (byte*)scan0.ToPointer();"
Ben moi, il y a que
byte* p = (byte*)scan0.ToPointer();
... qui passe à la compilation.
cs_yoannd
Messages postés305Date d'inscriptionlundi 7 janvier 2002StatutMembreDernière intervention10 août 20117 9 déc. 2004 à 18:47
Alors, les erreurs, il y en a quelques une, en effet, mais rien de bien méchant :
Bitamp bmp = new Bitmap(ImageOrigine,ImageOrigin.Width,ImageOrigin.Height);
on préferrera déclarer un Bitmap plutot qu'un Bitamp et le vairable ImageOrigin n'existe pas, il faut écrire ImageOrigine
Je suppose que tu as voulu écrire ca
int nOffset = scanline-bmp.Width*3;
...à la place de
int nOffset = stride-bmp.Width*3;
Par contre, tu écris aussi ceci :
Image imgOut = Image.FromHBitmap(newBmp.GetHBitmap());
mais mon compilo ne trouve pas les fonction FromHBitmap et GetHBitmap. Est-ce qu'il me manque des using ? Ha non, je viens de voir que FromHbitmap avec un b minuscule fonctionnait, ainsi que GetHbitmap.
D'ailleurs, ce serait pas mal de les indiquer. Il me semble qu'il nous faut ici les using suivants :
using System.Drawing;
using System.Drawing.Imaging;
De plus, il ne me semble jamais avoir entendu que ++x et x++ étaient différents en terme de rapidité, mais la différence, c'est que si j'écris :
x = 3;
Console.WriteLine("" + (x++));
Ca m'affiche 3, puis ca incrémente de 1 la valeur x, alors que si j'écris :
Console.WriteLine("" + (++x));
ben ca incrémente de un la valeur x puis ca affiche 3+1, soit 4.
Bon, passons sur ceci, ce qui m'embète un peu plus, c'est que j'ai testé ce code, et ca me donne une image qui ne contient que des bandes grises et noires, bref, donc voila, heuuu, je crois qu'il y a un bug. En tout cas, c'est tout de même un contribution et ca peut peut-être aider quelqu'un, c'est le point positif de la chose. Mais c'est vrai qu'un petit zip, ca aurait été cool.
1 avril 2008 à 16:31
Je veux juste vous poser une question concernant le traitement d'images, bon je veux mettre une bar de zoom sur une image mais il faut quelle soit transparente comme la boussole du google earth, merci de votre reponse.
5 mars 2008 à 08:37
13 déc. 2007 à 13:04
je ne connaissais le mode unsage qu'en théorie, j'en ai eu besoin récement donc je me suis très largement inspiré de ton code pour comprendre le principe et le mettre en application donc merci :)
Remarque: Si vous souahitez gérer la transparence des png, passez en Format32bppARgb et remplacez les 3 par des 4 lors de la copie des pixels (une constante aurait été bienvenue)
en tout cas merci :)
13 févr. 2007 à 10:37
Avec le mode "unsafe", sur une belle image de la lune avec une petite résolution de 5900x3100 siouplé :-) tous mes filtres prennent maxi 3sec !
Un grand merci à toi pour ce joli code qui m'a fait découvrir la puissance des pointeurs ;-)!
21 juil. 2006 à 10:33
Merci pour ton code, il m'a permis d'inverser la couleur de mes graphiques avant l'impression, c'est tres pratique pour économiser le noir !
26 mars 2006 à 19:20
Je me suis inspiré de ton code pour optimiser une déformation d'image (pour faire de l'assemblage horizontal de photo). C'est vrai que c'est nettement plus efficace. Merci beaucoup.
26 mars 2006 à 18:00
fonction(i); i = i+1;
et
i=i+1; fonction(i);
respectivement,
donc pour la vitesse, j'ai un doute ;)
17 nov. 2005 à 21:44
11 déc. 2004 à 09:41
on peut aussi utiliser les fonction "GetPixel()" et "SetPixel()" de la classe Bitmap pour travailler les pixels.
mais ces méthodes sont "très" lentes par rapport à l'utilisation de pointeurs.
Sur MSDN il y a un article interressant là dessus.
l'auteur y écrit qu'en Managed Code (getpixel,setpixel) son filtre Grayscale s'applique en 14sec. (enormement long mdr) , en Unmanaged (pointeurs) : 0.52sec ; )
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp11152001.asp
par contre je vois pas trop ce que tu as fais pour ton test entre Managed et Unmanaged , tu extraits ton bitmap de 2 manieres differente et tu lui appliques mon filtre ? o_o
Sinon mon avis général sur la question c'est que l'étude des pointeurs va me permettre beaucoup de choses impossible à faire en managed code ^^"
wallou
++
11 déc. 2004 à 00:53
Je viens de réaliser quelques tests entre ta methode et celle consistant à extraire le graphics du bitmap et travailler directement dessus.
Je me suis permis de modifier un peu ton source afin de laisser la possibilité d'importer une image et par suite remplacer celle par défaut. J'importe une bitmap de taille importante (105 Mo) afin de voir les temps de calculs et la mémoire prise (je suis sur un XP2000+ à 512 DDR).
L'application d'un filtre selon ta methode prend environ 6 à 7 secondes à pleine puissance (je parle ici de travail sans effet mémoire pour la possibilité d'annulation afin de ne pas être inflencé par des éventuel swappages).
La même opération effectuée sur une bitmap par extraction du graphics prends exactement le même temps.
Tout ceci pour pauser la question de l'utilité du mode "unsafe". C'est effectivement une question qui me tracasse pas mal car d'une part, le mode managé permet une certaine "sécurité" du code mais est sensé ralentir quelque peut l'exécution. Malheureusement pour moi, chaque exemple que je peux tester ne me permet pas réellement de trancher sur un mode plutôt que l'autre.
Pourrais tu m'éclarrer sur ton choix (travail en mode unsafe) et ton avis général sur la question ???
D'avance encore merci
11 déc. 2004 à 00:15
Je viens de lire ton poste et ta methode me parrait effectivement intéressante.
J'aurais aimé avoir une sorte de comparatif ou tout du moins d'ordre d'idée concernant la différence de rapidité d'exécution entre le principe que tu décris (parcourt par pointeur etc) et le fait de rester en mode managé et dessiner la bitmap en passant par un objet "graphics".
Effectivement je ne parle pas là de modification de luminosité ou autre mais bien de dessin à proprement parler d'une bitmap. Je sais que ce n'est pas directement le sujet mais un rapport tout de même étroit m'a poussé a écrire ce poste.
Merci d'avance pour ta réponse
10 déc. 2004 à 09:32
tu viens de donner pas mal de valeur à ta source là, d'un coup ! ben bravo, je trouve ca extra !
9 déc. 2004 à 21:18
Effectivement , y avait quelques fautes mdr ....
J'ai tout corrigé (je pense .... ) et j'ai rajouté un zip avec quelques filtres supplémentaires pour me faire pardonner v( ^_^ )v .
J'ai voulu faire le chaud et tout taper de tête en postant ma source , c'est à cause de ça qu'y avait autant de fautes ....j'aurais dû faire un vieux copier/coller xD
C'est vrai que j'aurais dû parler des namespaces ,
Je m'en excuse !!
Pour "++i" ou "i++" t'as peut être raison, je pensait avoir vu ça dans la version de msdn fournit dans vs.net ... à vérifier ...
et pour la déclar. du pointeur moi les 2 passent niquel o_O , mais je me sert que de "(byte*)(void*)scan0"
Réessayes avec la source de mon zip. : /
on sait jamais ...
Ciao
9 déc. 2004 à 18:52
byte* p = (byte*)(void*)scan0;
//on peut aussi écrire "byte* p = (byte*)scan0.ToPointer();"
Ben moi, il y a que
byte* p = (byte*)scan0.ToPointer();
... qui passe à la compilation.
9 déc. 2004 à 18:47
Bitamp bmp = new Bitmap(ImageOrigine,ImageOrigin.Width,ImageOrigin.Height);
on préferrera déclarer un Bitmap plutot qu'un Bitamp et le vairable ImageOrigin n'existe pas, il faut écrire ImageOrigine
Je suppose que tu as voulu écrire ca
int nOffset = scanline-bmp.Width*3;
...à la place de
int nOffset = stride-bmp.Width*3;
Par contre, tu écris aussi ceci :
Image imgOut = Image.FromHBitmap(newBmp.GetHBitmap());
mais mon compilo ne trouve pas les fonction FromHBitmap et GetHBitmap. Est-ce qu'il me manque des using ? Ha non, je viens de voir que FromHbitmap avec un b minuscule fonctionnait, ainsi que GetHbitmap.
D'ailleurs, ce serait pas mal de les indiquer. Il me semble qu'il nous faut ici les using suivants :
using System.Drawing;
using System.Drawing.Imaging;
De plus, il ne me semble jamais avoir entendu que ++x et x++ étaient différents en terme de rapidité, mais la différence, c'est que si j'écris :
x = 3;
Console.WriteLine("" + (x++));
Ca m'affiche 3, puis ca incrémente de 1 la valeur x, alors que si j'écris :
Console.WriteLine("" + (++x));
ben ca incrémente de un la valeur x puis ca affiche 3+1, soit 4.
Bon, passons sur ceci, ce qui m'embète un peu plus, c'est que j'ai testé ce code, et ca me donne une image qui ne contient que des bandes grises et noires, bref, donc voila, heuuu, je crois qu'il y a un bug. En tout cas, c'est tout de même un contribution et ca peut peut-être aider quelqu'un, c'est le point positif de la chose. Mais c'est vrai qu'un petit zip, ca aurait été cool.