Analyse d'une zone de l'image

Résolu
Utilisateur anonyme - 17 avril 2006 à 05:58
 Utilisateur anonyme - 19 avril 2006 à 06:27
Bonjour,



Dans mon application, je dois analyser une image et la couleur de ses
pixels, cela est facilement realisable par la methode GetPixel() mais
pour des raisons de rapidite, il est preferable d'utiliser du code
unsafe auquel, je dois le reconnaitre, je n'ai pas tout tout compris.
Mon probleme est que je dois adapter mon code pour laisser la
possibilite a l'utilisateur de n'analyser qu'une partie de l'image et
je n'arrive pas a adapter le code unsafe pour cet emploi, voici le code
:



// Create a new bitmap picture to work on it


Bitmap bmp = new
Bitmap(blackandwhite,blackandwhite.Width,blackandwhite.Height);

// It's in a BitmapData where Lockbits is used


// So we do data Lockbits of our bitmap


System.Drawing.Imaging.BitmapData bmpData =
bmp.LockBits(newRectangle(0,0,bmp.Width,bmp.Height),System.Drawing.Imaging.ImageLockMode.ReadOnly,System.Drawing.Imaging.PixelFormat.Format24bppRgb);

// Now take some informations


int scanline = bmpData.Stride; // stride (or
scanline) is the widthof a pixels row in this picture


IntPtr scan0 = bmpData.Scan0; // Scan0 indicate
where is the first pixel in the memory



long alpha = 0;




// To be faster, we must use pointers and to use
pointers

// We need to code the program in "unsafe" mode

unsafe

{

// "p" will be the pointer

byte* p = (byte*)(void*)scan0;


// It's also possible to write :
"byte* p = (byte*)scan0.ToPointer();"




int nOffset =
scanline-bmp.Width*3;

int nWidth = bmp.Width*3;

byte r; // red

byte g; // green

byte b; // blue



// For each pixel in the height


for(int y = 0 ; y < Height ;
++y)

{


// For each
pixel in the width


for( int x = 0
; x < nWidth ; ++x)

{



b = p[0];



g = p[1];



r = p[2];



// If the pixel is white



if(r 255 && g 255 & b == 255)



{



++alpha;



}



++p;

}

p+=nOffset;

}

}

// When it's done, slacken data

bmp.UnlockBits(bmpData);

bmp.Dispose();



Si vous pouviez m'indiquer comment modifier le code pour pouvoir
analyser une zone de selection predefinie en expliquant le pourquoi, je
vous en serais tres reconnaissant.

12 réponses

bob94700 Messages postés 69 Date d'inscription jeudi 13 février 2003 Statut Membre Dernière intervention 7 avril 2007 4
17 avril 2006 à 10:59
Salut,
Essaye ce bout de code :

private void TestFunction (Image SrcImg, Rectangle Zone)
{
// Create a new bitmap picture to work on it
Bitmap bmp = new Bitmap(SrcImg, SrcImg.Width, SrcImg.Height);
System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(new Rectangle(0,0,bmp.Width,bmp.Height),System.Drawing.Imaging.ImageLockMode.ReadWrite,System.Drawing.Imaging.PixelFormat.Format24bppRgb);
int scanline = bmpData.Stride; // stride (or scanline) is the widthof a pixels row in this picture
IntPtr scan0 = bmpData.Scan0; // Scan0 indicate where is the first pixel in the memory
long alpha = 0;

unsafe
{
// "p" will be the pointer
byte* p = (byte*) scan0.ToPointer();
int nOffset = scanline - 3 * Zone.Width;
byte r; // red
byte g; // green
byte b; // blue
int y, x;

// Point de départ dans le tableau de pixel en fonction de la zone demandée et de la taille de l'image :
p += 3 * (Zone.X + Zone.Y * SrcImg.Width);

for(y = 0 ; y < Zone.Height ; ++y)
{
// For each pixel in the width
for(x = 0 ; x < Zone.Width ; ++x)
{
b = *p++; // Recupère la valeur, puis déplace le pointeur de 1
g = *p++;
r = *p++;
// If the pixel is white if(r 255 && g 255 & b == 255)
{
++alpha;
}
// On incrémente de 3 car on est en Format24bppRgb et on évite les recouvrement entre les points !
// inutile si on définit b = *p++; etc...
// p += 3;
}
p+=nOffset;
}
}

bmp.UnlockBits(bmpData);
bmp.Dispose();
}
3
MorpionMx Messages postés 3466 Date d'inscription lundi 16 octobre 2000 Statut Membre Dernière intervention 30 octobre 2008 57
17 avril 2006 à 11:10
Oui, voila, plus simplement

Ou alors tu clone ton image

// Pour travailler sur un rectangle de 100 * 100 a partir de la position (0;0)
bmp = bmp.Clone(
new
Rectangle(0, 0, 100, 100),
PixelFormat.Format24bppRgb);



Mx
MVP C#
1
bob94700 Messages postés 69 Date d'inscription jeudi 13 février 2003 Statut Membre Dernière intervention 7 avril 2007 4
17 avril 2006 à 11:04
Je me demande si plus simplement :
System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(Zone, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

ne suffirait pas ... et tu travailles sur la totalité de la zone.
0
Utilisateur anonyme
18 avril 2006 à 04:32
La deuxieme methode est beaucoup plus simple et fonctionne tres bien
quand on a pour pixel de depart le pixel (0,0) par contre, si on veut
selectionner une zone au milieu, par exemple (100,100,200,200), je ne
comprends pas pourquoi mais la fonction de clonage ne se fait pas, le
programme fait une exception "OutOfMemory".
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Utilisateur anonyme
18 avril 2006 à 04:57
Merci pour le code et les explications bob94700, mais je ne comprends pas bien le sens de cette ligne de code :



// Point de départ dans le tableau de pixel en fonction de la zone demandée et de la taille de l'image :


p += 3 * (Zone.X + Zone.Y *
SrcImg.Width);



Il est ecrit ce qu'elle fait mais...pourquoi cette addition des
coordonnees et cette multiplication avec la largeur de l'image source ?
0
Utilisateur anonyme
18 avril 2006 à 05:42
J'ai un autre probleme avec le code fournit, quand j'essaye de lire la
taille de la "Zone" (Zone.Height et Zone.Width) qui un rectangle que je
definie en fonction des choix de l'utilisateur. Si je lis la taille
dans la partie de code unsafe, j'obtiens toujours 0 alors que
si je lis la taille de la zone dans un autre endroit du programme,
j'obtiens bien le bon resultat. Le probleme est donc que le traitement,
qui est dans la partie de code unsafe doit se faire sur une image null donc autant dire que le traitement ne fonctionne pas. Serais je passe a cote de quelque chose ?
0
Utilisateur anonyme
18 avril 2006 à 07:07
Pour le premier des messages, j'ai compris mon erreur, je definissais
les coordonnes de la fin de ma zone de selection au lieu de definir la
largeur et la longueur (erreur stupide s'il en est). En effet, le code
etait tres simple a modifier, je vous remercie pour votre aide mais je
n'ai pas compris comment cette ligne fonctionne :



p += 3 * (Zone.X + Zone.Y * SrcImg.Width);
0
Utilisateur anonyme
18 avril 2006 à 09:15
Euh...c'est encore remoi, j'ai un autre probleme



J'execute cette petite partie de code dans un try catch et a chaque
execution, le prog trouve une exception on moment ou on recupere la
valeur et decale le pointeur. L'intitule exacte de l'exception est
Object reference is not set to an instance of an object. Une idee
sur ce que c'est ?
0
bob94700 Messages postés 69 Date d'inscription jeudi 13 février 2003 Statut Membre Dernière intervention 7 avril 2007 4
18 avril 2006 à 18:58
bonjour,
p est intialisé à : (byte*) scan0.ToPointer();
ce qui correspond au début du tableau qui représente l'image (le 1er point en quelque sorte).

Ce tableau contient w * h * 3 éléments (largeur * hauteur * nbre de byte par pixel, soit 3 en rvb24).

Maintenant si on commence au point de coordonnée (x,y) il faut se décaller d'un certains nombre point.
Ce nombre de point est :
le nbre de ligne entière qu'il faut passer, soit : y*w (on est en base 0)
+ le coordonnée x pour la dernière ligne : x
donc un total de : w*y + x
comme on est en rvb24, on multiplie le tout par 3 (byte par pixel). D'où le décalage de p avant la boucle.

L'erreur indique qu'une instance a la valeur "null". Ni ces propriétés, ni ces méthodes ne peuvent être utilisées. Maintenant, comme ça je ne sais pas quelle variable est "null". trace en débug tu devrais le voir très vite.
0
bob94700 Messages postés 69 Date d'inscription jeudi 13 février 2003 Statut Membre Dernière intervention 7 avril 2007 4
18 avril 2006 à 19:01
j'ai qd même un doute sur ton image : es-tu sûr qu'elle n'est pas null ? si c'est le cas, ajoute un
if (SrcImg == null)
return;

en début de la méthode.
0
Utilisateur anonyme
19 avril 2006 à 04:31
Merci beaucoup pour ces precisions, je suis certain d'avoir compris comment fonctionne le code maintenant.



Pour ce qui est de l'erreur, c'est ma faute, je veux aller trop vite et
j'en oublie, j'ai reussi a la corriger mais seuleument en partie car
elle reapparait certaines fois dans le programme, je ne sais pas ce qui
la declenche mais je vais chercher. Je te remercie pour ta tres
precieuse aide. Merci beaucoup.
0
Utilisateur anonyme
19 avril 2006 à 06:27
Mais je suis certain que l'image n'est pas null etant donne que l'analyse est OK et que je peux l'afficher.
0
Rejoignez-nous