Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Gráficos (https://www.clubdelphi.com/foros/forumdisplay.php?f=8)
-   -   Processamient de iMagens, Contador através de imagenes (https://www.clubdelphi.com/foros/showthread.php?t=59392)

coso 25-08-2008 22:07:02

hola,

Código Delphi [-]
 
function TForm1.Lluminositat(c : TColor): integer;
var
        r,g,b : integer;
        act : integer;
begin
       r := Red(c);
       g := Green(c);
       b := Blue(c);
       act := r+g+b;
       Lluminositat := act div 3;
end;
function TForm1.Red(c : TColor) : integer;
begin
        Red := c and $FF;
end;
function TForm1.Green(c : TColor) : integer;
begin
        Green := (c and $FF00) div $100;
end;
function TForm1.Blue(c : TColor) : integer;
begin
        Blue := (c and $FF0000) div $10000;
end;

si haces algo como

Código Delphi [-]
 
procedure filtro_de_contraste(cn : TCanvas);
var
i,j : integer;
begin
for i := 0 to cn.Width do
for j := 0 to cn.Height do
begin
 if Lluminositat(cn.Pixels[i,j]) > 128 then cn.Pixels[i,j] := clWhite
 else cn.Pixels[i,j] := clBlack;
end;
end;

tendras un filtro de contraste bastante aproximado. Solo hara falta aplicarlo antes. Si lo que quieres son deducir la direccion de degradado del color, puedes hacerlo tambien buscando el punto de maximo brillo (mediante lluminositat), restar con la luminosidad de los adyacentes, y aquel donde la diferencia (el gradiente) sea maximo, es el mas proximo al borde, aunque no creo que lo necesites.

Delphius 25-08-2008 22:23:07

Off-topic
 
Coso quería preguntarte, esto como off-topic, ¿porqué el uso de Pixels[]?:confused:
He visto que en otros hilos que tratas sobre el tema de pixeles, en tus códigos usas Pixels.
Yo me acostumbré a emplear Scanline. Tal vez se necesita un poco más de código pero me parece que se consigue mejor perfomance.

Yo he probado con imagenes relativamente grandes y el uso de scanLine por sobre Pixels se nota.

Saludos,

coso 25-08-2008 22:25:10

para q se entienda el algoritmo tansolo, luego si se tiene que optimizar, si se puede usar scanline o directamente operar en memoria

Cesar Junior 27-08-2008 04:25:39

Cita:

Empezado por coso (Mensaje 309358)
hola,


Código Delphi [-]

function TForm1.Lluminositat(c : TColor): integer;
var
r,g,b : integer;
act : integer;
begin
r := Red(c);
g := Green(c);
b := Blue(c);
act := r+g+b;
Lluminositat := act div 3;
end;
function TForm1.Red(c : TColor) : integer;
begin
Red := c and $FF;
end;
function TForm1.Green(c : TColor) : integer;
begin
Green := (c and $FF00) div $100;
end;
function TForm1.Blue(c : TColor) : integer;
begin
Blue := (c and $FF0000) div $10000;
end;





si haces algo como


Código Delphi [-]

procedure filtro_de_contraste(cn : TCanvas);
var
i,j : integer;
begin
for i := 0 to cn.Width do
for j := 0 to cn.Height do
begin
if Lluminositat(cn.Pixels[i,j]) > 128 then cn.Pixels[i,j] := clWhite
else cn.Pixels[i,j] := clBlack;
end;
end;






tendras un filtro de contraste bastante aproximado. Solo hara falta aplicarlo antes. Si lo que quieres son deducir la direccion de degradado del color, puedes hacerlo tambien buscando el punto de maximo brillo (mediante lluminositat), restar con la luminosidad de los adyacentes, y aquel donde la diferencia (el gradiente) sea maximo, es el mas proximo al borde, aunque no creo que lo necesites.




procedure Comic(Img: TPicture; Umbral: Integer);
var
Bitmap: TBitmap;
P1,P2,P3,P4: PByte;
i,j: Integer;
begin
Bitmap:= TBitmap.Create;
try
Bitmap.Width:= Img.Width;
Bitmap.Height:= Img.Height;
Bitmap.Canvas.Draw(0,0,Img.Graphic);
if not (Img.Graphic is TBitmap) then
Img.Assign(Bitmap);
Img.Bitmap.PixelFormat:= pf24bit;
Bitmap.PixelFormat:= pf24bit;
for j:= -1 to Bitmap.Height - 2 do
begin
// Ajustamos el borde superior
if j < 0 then
P1:= Bitmap.ScanLine[0]
else
P1:= Bitmap.ScanLine[j];
P2:= Bitmap.ScanLine[j+1];
// Ajustamos el borde inferior
if j > Bitmap.Height - 3 then
P3:= Bitmap.ScanLine[Bitmap.Height - 1]
else
P3:= Bitmap.ScanLine[j+2];
P4:= Img.Bitmap.ScanLine[j+1];
// Primera columna
PFila(P4)[1]:=
Calcular(PFila(P1),PFila(P2),PFila(P3),1,2,Umbral);
for i:= 0 to Bitmap.Width - 3 do
begin
PFila(P4)[2]:=
Calcular(PFila(P1),PFila(P2),PFila(P3),2,3,Umbral);
inc(P1,Sizeof(TRGB));
inc(P2,Sizeof(TRGB));
inc(P3,Sizeof(TRGB));
inc(P4,Sizeof(TRGB));
end;
// Ultima columna
PFila(P4)[2]:=
Calcular(PFila(P1),PFila(P2),PFila(P3),2,2,Umbral);
end;
finally
Bitmap.Free;
end;
end;


Esto que fue postado aqui da un resultado mui bueno, e intentado trabajar con el primer algoritmo que me passaste pero no logre exito con el, tbm é intentado el recursivo pero tampoco me dio resultados, cae que parece simples, pero ya veo q no lo es tanto

Cesar Junior 27-08-2008 04:31:16

procedure limiar(ABmp: TBitmap);
var
c: TCursor;
x, y: Integer;
R, G, B: Byte;
ColorRGB: LongInt;
HCLR: Byte;
begin
Li := Limiarizar; // variable global q recibe el valor de Limiar
c := Screen.Cursor;
Screen.Cursor := crHourGlass;
for y := 0 to (ABmp.Height - 1) do
for x := 0 to (ABmp.Width - 1) do begin
ColorRGB := ColorToRGB(ABmp.Canvas.Pixels[x, y]);
// obtém as cores da paleta
R := GetRValue(ColorRGB);
G := GetGValue(ColorRGB);
B := GetBValue(ColorRGB);
// compara valor
HCLR := 0;
if R > Li then HCLR := 255;
if G > Li then HCLR := 255;
if B > Li then HCLR := 255;
// converte para tons de cinza
R := HCLR;
G := HCLR;
B := HCLR;


// aplica a nova cor ao pixel
ABmp.Canvas.Pixels[x, y] := PaletteRGB(R, G, B);
end;
Screen.Cursor := c;
end;


Consiste que con esto conseguimos binarizar la imagen de acuerdo con la necessidad de cada, o sea que como una imagen en escala de grizes varia de 0 a 255 ejemplo de lmiar 127 todo aquells pixels q estean abajo de 127 van a 0 (negro) y todos los que estean arriba de 127 van a 255(blanco), esto da resultados mas preciso dependiendo de la imagen, al resultado de esto estoy intentando implementar algo

Delphius 27-08-2008 04:36:12

Hola Cesar Junior,
¿Avanzaste en algo?

Cuando coloques código, por favor usa la etiquetas [ DELPHI ] [ /DELPHI ] (sin los espacios) para que el código se resalte mejor.

Saludos,

coso 27-08-2008 10:14:59

es extraño, si consigues pasarlo todo a manchas blancas, el primer algoritmo te las cuenta...¿porque te falla?

Cesar Junior 27-08-2008 13:34:24

Cita:

Empezado por coso (Mensaje 309627)
es extraño, si consigues pasarlo todo a manchas blancas, el primer algoritmo te las cuenta...¿porque te falla?

En realidad no me las cuenta, me la passa todo lo que es blanco a negro, y depues dibuja una elipse Randon, q la passa a rojo, es extraño tenter cambiar algunas cosas pero no me dio resultado

coso 27-08-2008 13:54:15

ah....vamos, que no entendiste nada

coso 27-08-2008 13:57:36

El algoritmo esta integrado en un ejemplo que pinta todo de negro y luego dibuja unas elipses blancas para contarlas. Luego recorre cada pixel y si encuentra alguno de color blanco, lo pinta de otro color y aumenta el contador de zonas. La parte util para ti supongo que tendria que ser aquella que recorre cada pixel y rellena, y no la que dibuja las elipses.

Cesar Junior 27-08-2008 23:23:45

Cita:

Empezado por coso (Mensaje 309665)
ah....vamos, que no entendiste nada


Si, en verdad que tenes razon, es que soy aprendiz, y me di cuenta de q no estava entendiendo nada, rs.. hize unos experimentos com grano de maíz, y tu algoritmo funciona muy bien, solo ay q estudiar una forma de mejorar la imagen cuando loa sgranos estan muy juntos me da un valor aproximado, pero te agradesco mucho q en reaqlidad funciona muy bien!!!

Cesar Junior 27-08-2008 23:28:22

Y quedo asi
Código Delphi [-]
 
procedure TForm1.Rellena_colonia(i,j : integer; col,rel : TColor; im : TImage);
begin
        Im.Canvas.Brush.Color := rel;
        Im.Canvas.FloodFill(i,j,col,fsSurface);
end;
 
 
procedure TForm1.BitBtn6Click(Sender: TObject);
var
        i,j : integer;
        colonias : integer;
begin
        colonias := 0;
        for i := 0 to Image1.Width do
        for j := 0 to Image1.Height do
        if Image1.Canvas.Pixels[i,j] = clWhite then
        begin
             rellena_colonia(i,j,clWhite,clRed,Image1);
             inc(colonias);
        end;
        Label2.Caption := inttostr(colonias);
        Label2.Visible:=true;
        ShowMessage(inttostr(Colonias));
end;

Esto funciona mui bien, cuando la imagen esta bien definida

Cesar Junior 28-08-2008 04:21:39

Cita:

Empezado por seoane (Mensaje 309348)
Pues yo también me voy a meter :D Si lo que queremos es contar manchas, porque no difuminamos bien la imagen, y luego le aplicamos un "umbral". Seguramente las formas que queden sean lo bastante simples y definidas para que no tengamos problemas en encontrarlas.

De todas formas seria interesante un algoritmo que además de localizar la mancha nos dijera su tamaño, no es lo mismo una mancha de 1 pixels que de 100x100, podría interesarnos descartar las que fueran demasiado pequeñas


Esto de definir un tamanho con un algoritmo se ve interessante que camino devo seguir?

coso 28-08-2008 11:23:52

Hola de nuevo Cesar Junior,

Código Delphi [-]
        colonias := 0;
        for i := 0 to Image1.Width do
        for j := 0 to Image1.Height do
        if Image1.Canvas.Pixels[i,j] = clWhite then
        begin 
             tam := 0;
             rellena_colonia(i,j,clWhite,clRed,Image1,tam);
             ShowMessage(inttostr(tam)); // tamaño de colonia
             inc(colonias);
        end;
        Label1.Caption := inttostr(colonias);
end;

procedure TForm1.Rellena_colonia(i,j : integer; col,rel : TColor; im : TImage; var tam : integer);
begin
        if (i = 0) or (j = 0) or (i > Im.Width) or (i > Im.Height) then exit;
        if Im.Canvas.Pixels[i,j] <> col then exit;
        Im.Canvas.Pixels[i,j] := rel;
        inc(tam);

        rellena_colonia(i-1,j-1,col,rel,im,tam);
        rellena_colonia(i  ,j-1,col,rel,im,tam);
        rellena_colonia(i+1,j-1,col,rel,im,tam);
        rellena_colonia(i-1,j  ,col,rel,im,tam);
        rellena_colonia(i  ,j  ,col,rel,im,tam);
        rellena_colonia(i+1,j  ,col,rel,im,tam);
        rellena_colonia(i-1,j+1,col,rel,im,tam);
        rellena_colonia(i  ,j+1,col,rel,im,tam);
        rellena_colonia(i+1,j+1,col,rel,im,tam);
end;
te ira contando los tamaños

Cesar Junior 28-08-2008 15:08:23

Cita:

Empezado por coso (Mensaje 309930)
Hola de nuevo Cesar Junior,


Código Delphi [-]
colonias := 0;
for i := 0 to Image1.Width do
for j := 0 to Image1.Height do
if Image1.Canvas.Pixels[i,j] = clWhite then
begin
tam := 0;
rellena_colonia(i,j,clWhite,clRed,Image1,tam);
ShowMessage(inttostr(tam)); // tamaño de colonia
inc(colonias);
end;
Label1.Caption := inttostr(colonias);
end;

procedure TForm1.Rellena_colonia(i,j : integer; col,rel : TColor; im : TImage; var tam : integer);
begin
if (i = 0) or (j = 0) or (i > Im.Width) or (i > Im.Height) then exit;
if Im.Canvas.Pixels[i,j] <> col then exit;
Im.Canvas.Pixels[i,j] := rel;
inc(tam);

rellena_colonia(i-1,j-1,col,rel,im,tam);
rellena_colonia(i ,j-1,col,rel,im,tam);
rellena_colonia(i+1,j-1,col,rel,im,tam);
rellena_colonia(i-1,j ,col,rel,im,tam);
rellena_colonia(i ,j ,col,rel,im,tam);
rellena_colonia(i+1,j ,col,rel,im,tam);
rellena_colonia(i-1,j+1,col,rel,im,tam);
rellena_colonia(i ,j+1,col,rel,im,tam);
rellena_colonia(i+1,j+1,col,rel,im,tam);
end;




te ira contando los tamaños


Sensacional! esto funciona de maravilha!!! ahora voia definir cuales son los intereses para la contage, felicitaciones!!! se nota que para ti es de una simplicidad, cuando ya para mi parecia un monstro de 7 cabezas, asi q tenga los resultados posto aqui para mostrarles, des de ya gracias a todos con las ideas el tiepo tomado, a Coso, [DELPHIUS], seoane!!!

coso 28-08-2008 19:49:42

de nada ;)


La franja horaria es GMT +2. Ahora son las 08:42:54.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi