Port new method for img object

Hello everyone.
You have a great approach using micropython for machine vision. This way some low or middle level coders can use it for DIY projects.
So Could you please explain me what I make wrong?
I want to add new method for image object which based on Zhang-Suen thinning algorithm.

My idea is:

  1. I make a snapshot by img = sensor.snapshot().lens_corr(strength = 1.45, zoom = 1.0)
  2. Convert image to bitmap by using img.to_bitmap()
  3. Then I want to use my own method img.ZhangSueng()
  4. Then print result in IDE by the next command print(img.compressed_for_ide(), end = “”) to check result

I have already created C functions and add them to imlib.c file

void image_put_binary_pixel(image_t *ptr, int x, int y, int pixel_val)
{
	IMAGE_PUT_BINARY_PIXEL(ptr, x, y, pixel_val);
}

bool image_get_binary_pixel(image_t *ptr, int x, int y)
{
	return IMAGE_GET_BINARY_PIXEL(ptr, x, y);
}
            

int getBlackNeighbours(image_t *ptr, int row,int col)
{

	int i, j, sum = 0;

	for(i=-1; i<=1; i++){
		for(j=-1; j<=1; j++){
			if(i!=0 || j!=0)
				sum+=  (image_get_binary_pixel(ptr, col + 1, row + 1) == 1);          
		}
	}
	return sum;
}

int getBWTransitions(image_t *ptr, int row, int col){
	return 	  ((image_get_binary_pixel(ptr, col - 1, row)==0 && image_get_binary_pixel(ptr, col - 1, row + 1)==1)
				+(image_get_binary_pixel(ptr, col - 1, row + 1)==0 && image_get_binary_pixel(ptr, col, row + 1)==1)
				+(image_get_binary_pixel(ptr, col , row + 1)==0 && image_get_binary_pixel(ptr, col + 1, row + 1)==1)
				+(image_get_binary_pixel(ptr, col + 1 , row + 1)==0 && image_get_binary_pixel(ptr, col + 1, row)==1)
				+(image_get_binary_pixel(ptr, col + 1, row)==0 && image_get_binary_pixel(ptr, col + 1, row - 1)==1)
				+(image_get_binary_pixel(ptr, col + 1, row - 1)==0 && image_get_binary_pixel(ptr, col + 1, row - 1)==1)
				+(image_get_binary_pixel(ptr, col , row - 1)==0 && image_get_binary_pixel(ptr, col - 1 , row - 1)==1)
				+(image_get_binary_pixel(ptr, col - 1, row - 1)==0 && image_get_binary_pixel(ptr, col - 1 , row)==1));
}

int zhangSuenTest1(image_t *ptr, int row,int col){
	int neighbours = getBlackNeighbours(ptr, row, col);

	return ((neighbours>=2 && neighbours<=6)
		&& (getBWTransitions(ptr, row,col)==1)
		&& (image_get_binary_pixel(ptr, col - 1, row)==0 || image_get_binary_pixel(ptr, col, row+1)==0 || image_get_binary_pixel(ptr, col + 1, row)==0)
		&& (image_get_binary_pixel(ptr, col, row+1)==0 || image_get_binary_pixel(ptr, col + 1, row)==0 || image_get_binary_pixel(ptr, col, row-1)==0));
}


int zhangSuenTest2(image_t *ptr, int row, int col){
	int neighbours = getBlackNeighbours(ptr, row,col);

	return ((neighbours>=2 && neighbours<=6)
		&& (getBWTransitions(ptr, row, col)==1)
		&& (image_get_binary_pixel(ptr, col - 1, row)==0 || image_get_binary_pixel(ptr, col, row+1)==0 || image_get_binary_pixel(ptr, col, row - 1)==0)
		&& (image_get_binary_pixel(ptr, col - 1, row)==0 || image_get_binary_pixel(ptr, col+1, row)==0 || image_get_binary_pixel(ptr, col, row + 1)==0));
}

void zhangSuen(image_t *ptr){

	int startRow = 1, startCol = 1, i, j, count, processed;
    int endRow = 160-2;
	int endCol = 120-2;
	pxl* markers;

	do{
		markers = (pixel*)malloc((endRow-startRow+1)*(endCol-startCol+1)*sizeof(pxl));
		count = 0;
        // i - counter for rows - y coordinates
		// j - counter for columns - x coordinates 
		for( i = startRow; i <= endRow; i++){
			for( j = startCol; j <= endCol; j++){
				if(image_get_binary_pixel(ptr, j, i)== 1 && zhangSuenTest1(ptr, i, j) == 1){
					markers[count].row = i;
					markers[count].col = j;
					count++;
				}
			}
		}

		processed = (count>0);

		for( i = 0 ; i < count; i++){
			image_put_binary_pixel(ptr, markers[i].col, markers[i].row, 0);			
		}

		free(markers);
		markers = (pixel*)malloc((endRow-startRow+1)*(endCol-startCol+1)*sizeof(pxl));
		count = 0;

		for( i = startRow; i <= endRow; i++){
			for(j = startCol; j <= endCol; j++){
				if(image_get_binary_pixel(ptr, j, i) == 1 && zhangSuenTest2(ptr, i,j) == 1){
					markers[count].row = i;
					markers[count].col = j;
					count++;
				}
			}
		}

		if(processed==0)
			processed = (count>0);

		for(i=0;i<count;i++){
			image_put_binary_pixel(ptr, markers[i].col, markers[i].row, 0);	
		}

		free(markers);
	}while(processed==1);
}

In imlib.h I have next strings
typedef struct{
int row,col;
}pxl;

void image_put_binary_pixel(image_t *ptr, int x, int y, int pixel_val);
bool image_get_binary_pixel(image_t *ptr, int x, int y);
int getBlackNeighbours(image_t *ptr, int row, int col);
int getBWTransitions(image_t *ptr, int row, int col);
int zhangSuenTest1(image_t *ptr, int row,int col);
int zhangSuenTest2(image_t *ptr, int row, int col);
void zhangSuen(image_t *ptr);

In py_image.c
I have next

STATIC mp_obj_t py_image_zhangSuen(mp_obj_t img_obj)
{
 	mp_obj_t *image_t;
	
	imlib_zhangSuen(image_t);
    return img_obj;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_zhangSuen_obj, py_image_zhangSuen);

{MP_ROM_QSTR(MP_QSTR_zhangSuen),           MP_ROM_PTR(&py_image_zhangSuen)},

And in qstrdefsomv.h I added

Q(zhangSuen)

Project can be compiled. But my method doesn’t work. I think I have problems in py_image.c file
Please correct me if it is possible and explain my mistake.

You need to be more descriptive than it doesn’t work.

It takes a lot of time and effort to write algorithms in C. Generally, you should add printf() to you code and print out things as the algorithm runs to find the error.

You need to be more descriptive than it doesn’t work.

Sorry It is first time when I use forum to take help for coding.
I have my algorithm in python but processing speed doesn’t satisfy me. So it made me to write it on C.
I completely can’t understand how to “inform” micropython libs about existing new module and what objects this module should use.

I think I have some mistakes in this section.

STATIC mp_obj_t py_image_zhangSuen(mp_obj_t img_obj)
{
 	mp_obj_t *image_t;
	
	imlib_zhangSuen(image_t);
    return img_obj;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_zhangSuen_obj, py_image_zhangSuen);

{MP_ROM_QSTR(MP_QSTR_zhangSuen),           MP_ROM_PTR(&py_image_zhangSuen)},

I want my method to take img by object img.zhangSuen() and convert it so that to use converted img object for other purposes (for example print it in IDE).
Right now when I use img.zhangSuen() I get such message from OpenMV IDE: unindent does not match any outer indentation level.
Maybe you have tutorial concerning this topic???

STATIC mp_obj_t py_image_zhangSuen(mp_obj_t img_obj)
{
 	mp_obj_t *image_t;
	
	imlib_zhangSuen(image_t);
    return img_obj;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_zhangSuen_obj, py_image_zhangSuen);

Yeah, this doesn’t actually feed the image to the method. You need to do:

image_t *image_t= py_helper_arg_to_image_mutable(img_obj);

Please note, there’s no help support for editing the C code. Please ask questions that can’t be answered by observing other functions. If you have a very particular ask that covers something that’s not easy to figure out I’ll respond in detail. Otherwise, I’m going to be terse.

Wow. Thanks for quick response. My method start working as I wanted it to function.