aboutsummaryrefslogtreecommitdiffstats
path: root/random241sensor.py
blob: e9525e49c03fd7ceee6a9ffb6a72d4e1eb9a113a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#!/usr/bin/python2

import logging
import cv
import numpy as np
import time

# Bool to define wether to capture the cam or not
capture = True
# Bool to define wether to show the capture stream or not
showStream = True
white_threshold = 15.0
checked = np.zeros((1, 1), dtype=np.int)
mat = np.zeros((1, 1))
clusters = []
balances = []


def capture(camNumber, showStream):
    # Open stream for that camera
    logging.info('Capture from camera #%d', camNumber)
    cam = cv.CaptureFromCAM(int(camNumber))
    # Stream to output window as long as it is active
    return cam
    while capture:
        stream = cv.QueryFrame(cam)
        if showStream:
            cv.ShowImage("Americium 241", stream)


def set_capture(onOrOff):
    if onOrOff == bool:
        global capture
        capture = onOrOff


def frame_to_mat(img):
    cv.Smooth(img, img, cv.CV_GAUSSIAN, 3, 0)
    mat = cv.GetMat(img)
    frame_values = np.asarray(mat)
    return frame_values


# Convert a bgr matrix to grayscale
def bgr2gray(mat):
    b, g, r = mat[:, :, 0], mat[:, :, 1], mat[:, :, 2]
    gray = 0.1140 * b + 0.5870 * g + 0.2989 * r
    return gray


# Find a white dot in the black input matrix
def harvest_entropy(mat_input):
    global mat
    global checked
    global clusters
    global balances
    mat = mat_input.copy()
    if np.ndim(mat) >= 2:
        # Create array to hold the already checked pixels
        checked = np.zeros((len(mat), len(mat[0])), dtype=np.int)
        # Traverse the grayscale values in search of a bright pixel
        for i in range(0, len(mat) - 1):
            for j in range(0, len(mat[0]) - 1):
                # Check if it hasn't been checked yet
                if (checked[i][j] != 1):
                    # Find clusters, if the pixel is above threshold
                    if (mat[i][j] >= white_threshold):
                        #print "Hit above white threshold"
                        # Add a new cluster to the list of clusters
                        cluster = []
                        clusters.append(cluster)
                        # Find the rest of the cluster
                        find_cluster(i, j)
                        #print "Number at: %dx%dpx : %s" % (j, i, mat[i][j])
                checked[i][j] = 1
        # If there's one or more clusters, calculate its or their balance point
        if len(clusters) > 0:
            balance_point = cluster_to_balance_point()
            logging.info('%s, %s', balance_point[1], balance_point[0])
            #print balance_point
            # Empty the global clusters variable again
            del clusters[:]
            balances.append([time.time(), balance_point])
            mean = mean_balances()
            logging.info('%s, %s (balance mean)', mean[1], mean[0])
            floats = coordinate_to_float(balance_point[0], balance_point[1])
            logging.info('%s, %s (float)', floats[1], floats[0])
            #return balance_point
            return floats
    else:
        logging.error('Input matrix has wrong dimension!')


# Find cluster around a non-black pixel
def find_cluster(x, y):
    global checked
    global mat
    global clusters
    # Append the current white dot to the last cluster
    dot = np.array([x, y, mat[x][y]])
    clusters[len(clusters) - 1].append(dot)
    # Search for surrounding white dots now
    # Search one pixel further right
    if (len(mat) - 1 >= (x + 1)) and (mat[x + 1][y] >= white_threshold) \
            and (checked[x + 1][y] != 1):
        find_cluster(x + 1, y)
    # Search one pixel further right and down
    if (len(mat) - 1 >= (x + 1)) and (len(mat[0]) - 1 >= y + 1) and \
            (mat[x + 1][y + 1] >= white_threshold) \
            and (checked[x + 1][y] != 1):
        find_cluster(x + 1, y + 1)
    # Search one pixel further down
    if (len(mat[0]) - 1 >= y + 1) and \
            (mat[x][y + 1] >= white_threshold) and (checked[x][y + 1] != 1):
        find_cluster(x, y + 1)
    # Search one pixel further down and further left
    if (len(mat[0]) - 1 >= y + 1) and x - 1 >= 0 \
            and (mat[x - 1][y + 1] >= white_threshold) \
            and (checked[x - 1][y + 1] != 1):
        find_cluster(x - 1, y + 1)
    # Add this pixel to the list of checked pixels
    checked[x][y] = 1


# Create balance point from cluster
# TODO: Make possible to choose only most significant cluster
def cluster_to_balance_point():
    global clusters
    cluster_balances = []
    x_balance = 0.0
    y_balance = 0.0
    for cluster in clusters:
        mean_x = 0.0
        mean_y = 0.0
        sum_total = 0.0
        for dot in cluster:
            # Calculate X balance (x * intensity)
            mean_x = mean_x + dot[0] * dot[2]
            # Calculate Y balance (y * intensity)
            mean_y = mean_y + dot[1] * dot[2]
            # Calculate Y total (all intensity summed up)
            sum_total = sum_total + dot[2]
        # Add up the balances and put them into a list
        cluster_x_balance = mean_x / sum_total
        cluster_y_balance = mean_y / sum_total
        cluster_balances.append([cluster_x_balance, cluster_y_balance])
    # If it's more than one cluster, balance between them
    if len(cluster_balances) > 1:
        logging.info('Balancing between a couple of clusters.')
        total_cluster_x_balance = 0.0
        total_cluster_y_balance = 0.0
        for balance in cluster_balances:
            total_cluster_x_balance = total_cluster_x_balance + balance[0]
            total_cluster_y_balance = total_cluster_y_balance + balance[1]
        x_balance = total_cluster_x_balance / float(len(cluster_balances))
        y_balance = total_cluster_y_balance / float(len(cluster_balances))
    else:
        logging.info('Balancing between one cluster.')
        x_balance = cluster_x_balance
        y_balance = cluster_y_balance
    return [x_balance, y_balance]


# Displays the mean balance calculated from all balances
def mean_balances():
    global balances
    mean_balance = [0.0, 0.0]
    for balance in balances:
        mean_balance[0] = mean_balance[0] + balance[1][0]
        mean_balance[1] = mean_balance[1] + balance[1][1]
    mean_balance[0] = mean_balance[0] / float(len(balances))
    mean_balance[1] = mean_balance[1] / float(len(balances))
    return mean_balance


# Calculates float value between 0.0 and 1.0 from coordinate
# TODO: insert on-the-fly mean_balance as parameter
def coordinate_to_float(x, y):
    global mat
    width = float(len(mat))
    height = float(len(mat[0]))
#    balance_dim = [width / 2, height / 2]
    floatx = x / width
    floaty = y / height
    return [floatx, floaty]
# TODO: Function to calculate floats from mean_balance on the fly