viernes, 24 de octubre de 2008

Detección de rostros en PHP con Facedetect y OpenCV

Con el auge de las tecnologías de detección de rostros de las camaras fotográficas, decidi investigar un poco al respecto y me topé con la biblioteca OpenCV (Open Computer Visión Library). Esta biblioteca permite hacer análisis y transformaciónes a videos e imágenes así como detección de formas usando inteligencia artificial. Logré compilar una extensión para reconocimiento de personas en PHP llamada Facedetect el cual contiene dos funciones disponibles para enlazarlas con PHP5:

face_count(): Devuelve el numero de rostros encontradas en la imagen.
face_detect(): Devuelve un array con las coordenadas de los rostros disponibles.


Imágen sin procesar

Después de procesar
Numero de personas en la foto: 10


Monté la plataforma utilizando un servidor Ubuntu Hardy Heron con Apache2 y php5.

script:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;" />
<title>Detector de Rostros</title>
</head>
<body>
<h1>Open Computer Vision - Contador de personas</h1>
<form action="<?=$_SERVER['PHP_SELF']?>" method="post" ENCTYPE="multipart/form-data">
Archivo<input type="file" name="file">
<input type="submit" value="subir">
<input type="hidden" name="uploadflag" value="1">
</form>
<br>
<?php
if($_POST['uploadflag']==1){
if(
$_FILES['file']['tmp_name'] != ""){
$imagenfinal = "imagenes/foto".date("Ymdhis").".jpg";
$cascade = "/usr/local/share/opencv/haarcascades/haarcascade_frontalface_alt.xml";
move_uploaded_file($_FILES['file']['tmp_name'],$imagenfinal);
$format = strtolower(substr(strrchr($imagenfinal,"."),1));
switch(
$format)
{
case
'gif' :
$type ="gif";
$img = imagecreatefromgif($imagenfinal);
break;
case
'png' :
$type ="png";
$img = imagecreatefrompng($imagenfinal);
break;
case
'jpg' :
$type ="jpg";
$img = imagecreatefromjpeg($imagenfinal);
break;
case
'jpeg' :
$type ="jpg";
$img = imagecreatefromjpeg($imagenfinal);
break;
default :
die (
"<br>ERROR: tipo de archivo desconocido: $imagenfinal");
break;
}
$total = face_count($imagenfinal, $cascade);
$faces = face_detect($imagenfinal ,$cascade);

echo
"Numero de personas en la foto: ".$total;
$color = imagecolorallocate($img, 132, 135, 28);
for(
$i=0; $i<$total; $i++) {
$face = $faces[$i];
$x1 = $face['x'];
$y1 = $face['y'];
$x2 = $x1+$face['w'];
$y2 = $y1+$face['h'];
imagerectangle($img, $x1, $y1, $x2, $y2, $color);
echo(
"<br>persona ".($i+1)." : ($x1,$y1) - ($x2,$y2)");
}

if(
$total>0) {
$dest = "imagenes/nuevafoto_".date("Ymdhis").".jpg";
if(
$type=="gif") imagegif($img, $dest);
if(
$type=="jpg") imagejpeg($img, $dest);
if(
$type=="png") imagepng($img, $dest);
if(
$type=="bmp") imagewbmp($img, $dest);
echo
'<br><img src="'.$dest.'"><br>';
}
echo
'<a href="'.$_SERVER['PHP_SELF'].'"></a>';
} else{ echo
"<br>Debe subir una imagen<br>"; }
echo
'<br><br><a href="'.$_SERVER['PHP_SELF'].'">Recargar</a>';
}
?>
</body>
</html>

domingo, 15 de junio de 2008

Cheat para Word Challenge en Facebook

Aqui les dejo un bot generado en php para el famoso juego de facebook "Word Challenge". El programa genera un script en Windows Scripting Tool (vbs) que juega por ti.

"miscript.vbs"; // archivo de salida
$retardoinicial = 1800; // tiempo inicial de espera (en milisegundos) para hacer foco en la ventana del juego
$retardotecla = 0; //milisegundos
$diccionario = "xxxxxxxxxx"; // aqui va la pagina donde se obtienen las palabras
// esta pagina del diccionario deberan solicitármela por correo

function OutputFile($file) {
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; '
.'filename="'.$file.'"');
echo
file_get_contents($file);
}

function
SaveContent($content, $file)
{
if (
file_exists($file)) @unlink($file);
if (!
$handle = fopen($file, 'w')) die("Error in $file");
fwrite($handle,$content);
fclose($handle);
}

function ParseContent($string){
preg_match_all("(word=[a-zA-Z]{3}[a-zA-Z]*)", $string, $matches);
$rightwords = array();
foreach(
$matches[0] as $valor) $rightwords[] = substr($valor,5);
$rightwords = array_reverse(array_unique($rightwords));
return $rightwords;
}

if (
$_POST) {
srand((float)microtime() * 1000000);
$url = "http://$diccionario?letters=".substr($_POST['letras'],0,6).
"&dict=sowpods&Cheat=Cheat"
;
$input = @file_get_contents($url) or die('Cant access $url');
$rightwords = ParseContent($input);
$content = 'Dim Wsh'."\r\n";
$content.= 'Set Wsh = Wscript.CreateObject("Wscript.Shell")'."\r\n";
$content.= 'Wsh.AppActivate "Exploring"'."\r\n";
$content.= 'Wscript.sleep('.$retardoinicial.')'."\r\n";
foreach(
$rightwords as $word) {
$scriptline = '';
for(
$i=0; $i<strlen($word); $i++)
{
$letter = substr($word,$i,1);
$scriptline.='Wsh.SendKeys "{'.$letter.'}"'."\r\n";
}
$scriptline.='Wsh.SendKeys "{ENTER}"'."\r\n";
$content.=$scriptline;
}
SaveContent($content,"./".$scriptname);
OutputFile($scriptname);
exit();
}

?>
<html>
<body>
<h3>Generador de palabras para Word Challenge</h3>
<form name="miforma" method="post" action="<?=$_SERVER['PHP_SELF']?>">
<label>letras</label>
<input type="text" name="letras" />
<input type="submit" name="submit" value="submit">
<br>
</form>
</body>
</html>


miércoles, 5 de septiembre de 2007

Progress Bar en ASP.NET 2.0

Buscando Barras de progreso en Internet me topé con uno de esos controles dll que funcionaba a la perfección, pero pedia un donativo (practicamente shareware con alerta y todo) para el control. Asi que decidí ver como funcionaba y publicar mi propio control para uso público. Aqui les dejo el código fuente (ProgressBar.ascx y ProgressBar.ascx.vb)

ProgressBar.ascx

<% Control Language="VB" AutoEventWireup="false" CodeFile="ProgressBar.ascx.vb" Inherits="componentes_ProgressBar" %>
<table cellspacing="1" cellpadding="0" border="0" style="border-color:Blue;border-width:1px;border-style:solid;height:20px;width:200px;"><tr><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#0000ff;"></td><td style="background-color:#d3d3d3;"></td><td style="background-color:#d3d3d3;"></td><td style="background-color:#d3d3d3;"></td><td style="background-color:#d3d3d3;"></td><td style="background-color:#d3d3d3;"></td><td style="background-color:#d3d3d3;"></td><td style="background-color:#d3d3d3;"></td></tr></table>



ProgressBar.ascx.vb

Partial Class componentes_ProgressBar : Inherits System.Web.UI.UserControl
Private _forecolor As Color = Color.Blue
Private _backgroundcolor As Color = Color.LightGray
Private _width As String = "200px"
Private _valor As Integer = 0
Private _maxCuadros As Integer = 30

Public Property ForeColor() As Color
Get
Return
_forecolor
End Get
Set
(ByVal value As Color)
Me._forecolor = value
End Set
End Property

Public Property
BackgroundColor() As Color
Get
Return
_backgroundcolor
End Get
Set
(ByVal value As Color)
Me._backgroundcolor = value
End Set
End Property

Public Property
MaxCuadros() As Integer
Get
Return
_maxCuadros
End Get
Set
(ByVal value As Integer)
_maxCuadros
= value
End Set
End Property

Public Property
Width() As String
Get
Return
_width
End Get
Set
(ByVal value As String)
_width
= value
End Set
End Property

Function
ToHexColor(ByVal c As Color) As String
Return
"#" + c.ToArgb().ToString("x").Substring(2)
End Function

Public Property
Value() As Integer
Get
Return
_valor
End Get
Set
(ByVal value As Integer)
If value > 100 Then value = 100
If value < 0 Then value = 0
_valor = value
End Set
End Property

Protected Overrides Sub
Render(ByVal Output As HtmlTextWriter)
Dim i As Integer
Dim
vreal As Integer = CInt((_valor * _maxCuadros / 100) + 0.5)
Dim fcolor As String = ToHexColor(_forecolor)
Dim bcolor As String = ToHexColor(_backgroundcolor)
Dim c As String
Output.Write("<table cellspacing=""1"" cellpadding=""0"" border=""0"" style=""border-color:Blue;border-width:1px;border-style:solid;height:20px;width:" & _width & ";""><tr>")
For i = 1 To _maxCuadros
c
= IIf(vreal < i, bcolor, fcolor)
Output.Write(
"<td style=""background-color:" & c & ";""></td>")
Next
Output.Write("</tr></table>")
End Sub
End Class



domingo, 2 de septiembre de 2007

Selección múltiple con checkbox en Gridview

Muchas veces necesitamos ejecutar una acción para múltiples filas seleccionadas en un gridview a través de un checkbox, para ello lo primero que necesitamos es agregar la propiedad DataKeyNames con el ID primario de los datos que cargamos, asi podemos realizar las acciones necesarias accediendo individualmente a cada registro del GridView.

<asp:GridView id="gridview1" runat="server" DataKeyNames="id_persona" AutoGenerateColumns="False">
<Columns>
.
.

Aqui agregamos el TemplateField con el checkBox para insertarlo en el GridView...

.
.
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox id="chkMarca" runat="server"></asp:CheckBox>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>

Si queremos que las acciones se tomen sin necesidad de utilizar los eventos manejados por el GridView, podemos crear un Método que puede ser llamado directamente por un botón u otro control.


Private Sub EliminarPersonasSeleccionadas()
Dim persona as New Persona()
Dim iditem As Integer
For Each
dgi As GridViewRow In Me.gridview1.Rows
Dim ch As CheckBox = CType(dgi.FindControl("chkMarca"), CheckBox)
If ch.Checked Then
iditem = gridview1.DataKeys(dgi.DataItemIndex).Value
persona.id_persona
= iditem
persona.Eliminar()
End If
Next
End Sub



viernes, 24 de agosto de 2007

Exportar Gridview a Excel (ASP.NET 2.0)

Luego de buscar varias formas de exportar un gridview a excel de manera efectiva, encontré un método eficiente analizando varios códigos fuente. He aqui la manera de hacerlo con hojas de estilo css. Se deberá sobrecargar el método VerifyRenderingInServerForm justo como aparece para que la página no genere errores.


    Private Sub ExportarGridView(ByRef gv As GridView, Optional ByVal NombreArchivo As String = "datos.xls")

        gv.AllowPaging = False

        gv.AllowSorting = False

        ClearControls(gv)

        Me.EnableViewState = False

        Response.Buffer = True

        Response.ContentType = "application/vnd.ms-excel"

        Response.AddHeader("content-disposition", "attachment;filename=" _

        & NombreArchivo)

        Dim tw As New System.IO.StringWriter()

        gv.RenderControl(New HtmlTextWriter(tw))

        Response.Write("<HEAD><STYLE type=""text/css"">" _

        & ReadCss("~/ExportarExcel.css") & "<STYLE></HEAD>")

        Response.Write(tw.ToString)

        Response.End()

    End Sub

 

    Private Function ReadCss(ByVal arch As String) As String

        Dim archivo As String = Server.MapPath(arch)

        Dim flujoLectura As System.IO.StreamReader

        flujoLectura = System.IO.File.OpenText(archivo)

        Dim contenido As String = flujoLectura.ReadToEnd()

        flujoLectura.Close()

        Return contenido

    End Function

 

 

    Protected Sub ClearControls(ByRef control As Control)

        Dim i As Integer

        For i = control.Controls.Count - 1 To 0 Step -1

            ClearControls(control.Controls(i))

        Next i

        If Not TypeOf control Is TableCell Then

            If Not (control.GetType().GetProperty("SelectedItem") Is Nothing) Then

                Dim literal As New LiteralControl()

                control.Parent.Controls.Add(literal)

                Try

                    literal.Text = CStr(control.GetType().GetProperty("SelectedItem").GetValue(control, Nothing))

                Catch

                End Try

                control.Parent.Controls.Remove(control)

            Else

                If Not (control.GetType().GetProperty("Text") Is Nothing) Then

                    Dim literal As New LiteralControl()

                    control.Parent.Controls.Add(literal)

                    literal.Text = CStr(control.GetType().GetProperty("Text").GetValue(control, Nothing))

                    control.Parent.Controls.Remove(control)

                End If

            End If

        End If

        Return

    End Sub

 

 

    Public Overrides Sub VerifyRenderingInServerForm(ByVal control As System.Web.UI.Control)

 

    End Sub