Tortuosity in Python, test_code_#001
Tags: python, handwriting, numpy, computervision
Published: 2018-06-24 22:20:41

---
title: Tortuosity in Python, test_code_#001
published: true
description: Image descriptor in python
tags: python, handwriting, numpy, computervision
---

The tortuosity can be defined as *"It has irregular bends, curves and undulations and in different ways."* So the calculation of a descriptor *(and a index)* may represent the capacity of that sample *(person)* of produce tortuosity *(in general one calculate a mean and a std, I will not delve into those calculations)*. Another *(personal)* definition that i like is "if i take this point, how far can move without changing his direction" *(and perhaps, this definition was implemented)*.

In general this solution requiere a binary image *(handwritting)*. the procedure is create a copy layer *(that I call draft)* and then, depending on the conectivity, send to compute that binary matrix in a recursive way.

This code considers the connectivity by 4, and by 8, and I think that could be improvement by connectivity by 16.
*  By 4: horizontal and vertical.
* By 8: 4 plus their diagonals ( in 45°).
* *(by 16, every 22°)*

But for the problem that this code was created, the results in the test sets did not indicate the need for the extension of connectivity

####Code
```python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import math
import numpy as np

def __conect(image, pos, vect):
    limits = np.shape(image)
    if pos[0] < 0 or pos[0] == limits[0] or pos[1]< 0 or pos[1] == limits[1]:
        return 0
    elif image[pos]:
        return 1+__conect(image,(pos[0]+vect[0],pos[1]+vect[1]),vect)
    return 0

def conect(image, label=4):
    draft = np.zeros(np.shape(image)).astype(int)
    image = image.astype(bool)
    pos=np.where(image==True)
    for i in range(len(pos[0])):
        weights = []
        if label in [4, 8]:
            weights.append(__conect(image,(pos[0][i],pos[1][i]+1),(0,1))+__conect(image,(pos[0][i],pos[1][i]-1),(0,-1))) #vertical
            weights.append(__conect(image,(pos[0][i]+1,pos[1][i]),(1,0))+__conect(image,(pos[0][i]-1,pos[1][i]),(-1,0))) #horizontal
        if label in [8]:
            weights.append(__conect(image,(pos[0][i]+1,pos[1][i]+1),(1,1))+__conect(image,(pos[0][i]-1,pos[1][i]-1),(-1,-1))) #slash
            weights.append(__conect(image,(pos[0][i]-1,pos[1][i]+1),(-1,1))+__conect(image,(pos[0][i]+1,pos[1][i]-1),(+1,-1))) #backsalsh
        draft[pos[0][i],pos[1][i]]= 1+max(weights)
    return draft


```
I like to consider this an example of named *(optional)* arguments, recursion, and move through a binary matrix without the *double **for***.

####Input
```python
image = np.array([[0,0,0,0,0,0,0],
[0,1,0,0,0,0,0],
[0,1,1,1,1,1,0],
[0,1,1,1,1,1,0],
[0,1,1,1,1,1,0],
[0,1,1,1,1,1,0],
[0,0,0,0,0,1,1]])
print("Original: \n", image)
print("Connect 4 (by default):\n", conect(image))
print("Connect set in 8:\n", conect(image, label=8))

```
####Output
```python
Original: 
 [[0 0 0 0 0 0 0]
  [0 1 0 0 0 0 0]
  [0 1 1 1 1 1 0]
  [0 1 1 1 1 1 0]
  [0 1 1 1 1 1 0]
  [0 1 1 1 1 1 0]
  [0 0 0 0 0 1 1]]
Connect 4 (by default):
 [[0 0 0 0 0 0 0]
  [0 5 0 0 0 0 0]
  [0 5 5 5 5 5 0]
  [0 5 5 5 5 5 0]
  [0 5 5 5 5 5 0]
  [0 5 5 5 5 5 0]
  [0 0 0 0 0 5 2]]
Connect set in 8:
[[0 0 0 0 0 0 0]
 [0 6 0 0 0 0 0]
 [0 5 6 5 5 5 0]
 [0 5 5 6 5 5 0]
 [0 5 5 5 6 5 0]
 [0 5 5 5 5 6 0]
 [0 0 0 0 0 5 6]]


```
* * * 
>  My *'test codes'* <br />
They are small sections of code for try something that maybe i don't know, or I don't want to test in the main project because of the iterance necesaries to work well. Usually are related with some current project *(work)*, sometimes are to improve something else *(debug, printing, algorithms, efficiency, etc...)*. <br />I have many of those files *(called test#.py or delete#.py)*, so, I will try to explain why I think they are interesting, and I hope that for you too. <br />*If you consider that I had bad English, I apologize, it is not my native language.*