I've been working on facial recognition and have obtained a dll that can recognize faces in an image, and gives cordinates aswell.
It came with an example program written in C++ and I'm trying to port it to python. Here is the C++ code

#include "windows.h"
#include "loadbmp.h" // from http://gpwiki.org/index.php/LoadBMPCpp
#include "fdlib.h"

void main(int argc, char *argv[]) 
{
	int i, n, x[256], y[256], size[256], w, h, threshold;	
	BMPImg *bi;
	unsigned char *bgrdata, *graydata;
	
	if (argc==1)
	{
	    printf("usage: fdtest bmpfilename [threshold]\n");
	    exit(0);
	}
		
	bi = new BMPImg();
	printf("\nloading %s\n", argv[1]);
	bi->Load(argv[1]);
	w = bi->GetWidth();
	h = bi->GetHeight();
	printf("image is %dx%d pixels\n", w, h);
	bgrdata = bi->GetImg();
	graydata = new unsigned char[w*h];
	
	for (i=0; i<w*h; i++)
	{
	    graydata[i] = (unsigned char) ((.11*bgrdata[3*i] + .59*bgrdata[3*i+1] + .3*bgrdata[3*i+2]));
	    //if (i<10) printf("%d ", graydata[i]);	    
	}	
	
	threshold = argc>2 ? atoi(argv[2]) : 0;
	printf("detecting with threshold = %d\n", threshold);
	fdlib_detectfaces(graydata, w, h, threshold);	
		
	n = fdlib_getndetections();
	if (n==1)
	    printf("%d face found\n", n);
	else
 	    printf("%d faces found\n", n);		
	
	for (i=0; i<n; i++)
	{
	    fdlib_getdetection(i, x+i, y+i, size+i);
	    printf("x:%d y:%d size:%d\n", x[i], y[i], size[i]);
	}
	
	delete[] graydata;
	delete bi;
}

The "bgrdata = bi->GetImg();" seems like it is the same as pythons Image modules getpixel(), as in returns a tuple of the RGB values for the given pixel. I could be wrong.

But what I need help with is the graydata.

for (i=0; i<w*h; i++)
	{
	    graydata[i] = (unsigned char) ((.11*bgrdata[3*i] + .59*bgrdata[3*i+1] + .3*bgrdata[3*i+2]));
	    //if (i<10) printf("%d ", graydata[i]);	    
	}

I know graydata is an array of grayscale values. I convert my image from RGB to grayscale with the Image module and then convert the each pixel value to a ctype to place in the graydata array:

while i < 307200: #size of image (640*480)
  graydata[i] = c_ubyte(gl[i]) #gl = list of grayscale values
  i += 1

but when I pass it to the dll i get:

>>> fd.fdlib_detectfaces(graydata, w, h, threshold)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: Procedure probably called with too many arguments (16 bytes in exces
s)

I didn't know whether to post this problem here, or in the C++ forums.
What am I doing wrong?

Recommended Answers

All 8 Replies

Your assumption about graydata is probably correct if you just follow GetImg() and pImage in header file loadbmp.h

Are you passing graydata in as a pointer?

I'm not sure what a pointer is, but I'm passing it as it is after:

i = 0
while i < 307200: #size of image (640*480)
  graydata[i] = c_ubyte(gl[i]) #gl = list of grayscale values
  i += 1

I just read something about pointers on google, would something like this work?

graydata = ctypes.cast(graydata, ctypes.POINTER(ctypes.c_ubyte))

I tried graydata = cast(graydata, POINTER(c_ubyte)) and fd.fdlib_detectfaces(byref(graydata), w, h, threshold) and still get the same error.

I don't think you can just dump a python array into the dll's function. Try initializing graydata like this:

graydata_type = ctypes.c_ubyte * (w * h)
graydata = graydata_type()

I do initialize it.

graydata = c_ubyte * (640*480)
graydata = graydata()

I figured that out when I assigned it the values:

i = 0
while i < 307200: #size of image (640*480)
  graydata[i] = c_ubyte(gl[i]) #gl = list of grayscale values
  i += 1

without you posting your code it's hard to know that <hint, hint>

Sorry about that.
I don't have any code, I've been doing all this through the interpreter. I didn't want to script anything until I know how to do it, and make sure it works.
Bascialy what I do is:

form ctypes import *
fd = windll.LoadLibrary('fdlib.dll')
import Image
im = Image.open('test.bmp') #test.bmp is a grayscale image of me.

x = 0
y = 0
l = []

while x*y <= (640*480): #this is to make a list of all the pixel values
  l.append(im.getpixel((x,y)):
  x+=1
  if x == 640:
    x = 0
    y+=1
  if y == 480:
    break

w= c_int(640)
h = c_int(480)
threshold = c_int(0) 
graydata = c_ubyte * (640*480)
graydata = graydata()

i = 0
while i < 307200: )
  graydata[i] = c_ubyte(l[i]) 
  i += 1

fd.fdlib_detectfaces(graydata, w, h, threshold)
#I've tried passing graydata as a pointer as stated on a previews reply
#But I might be making the pointer wrong or something

That's when I get the error.

I found it, after a week of google. fd = cdll.LoadLibrary('fdlib.dll') "cdll is for importing functions which use the cdecl calling convention
where the caller must clean up the stack. "(Found)

"windll is for functions that use the stdcall calling convention: the
function that is called is responsible for cleaning up the stack."(Found)

And thank you vegaseat for pointing out the pointers lol.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.