aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Runge <david.runge@frqrec.com>2014-01-31 11:48:32 +0100
committerDavid Runge <david.runge@frqrec.com>2014-01-31 11:48:32 +0100
commit9ea16a768cd4143d2a3508d7193f8d0d784e40be (patch)
tree44baccc06244854d8efc5814f2b13917a24a7e74
parentf36bab3657757251435c676f91991873387e324d (diff)
downloadrandom241-9ea16a768cd4143d2a3508d7193f8d0d784e40be.tar.gz
random241-9ea16a768cd4143d2a3508d7193f8d0d784e40be.tar.bz2
random241-9ea16a768cd4143d2a3508d7193f8d0d784e40be.tar.xz
random241-9ea16a768cd4143d2a3508d7193f8d0d784e40be.zip
First commit, still some TODOs
-rw-r--r--.ropeproject/config.py85
-rwxr-xr-xrandom241.py63
-rwxr-xr-xrandom241arg.py25
-rwxr-xr-xrandom241osc.py31
-rwxr-xr-xrandom241sensor.py157
5 files changed, 361 insertions, 0 deletions
diff --git a/.ropeproject/config.py b/.ropeproject/config.py
new file mode 100644
index 0000000..ffebcd4
--- /dev/null
+++ b/.ropeproject/config.py
@@ -0,0 +1,85 @@
+# The default ``config.py``
+
+
+def set_prefs(prefs):
+ """This function is called before opening the project"""
+
+ # Specify which files and folders to ignore in the project.
+ # Changes to ignored resources are not added to the history and
+ # VCSs. Also they are not returned in `Project.get_files()`.
+ # Note that ``?`` and ``*`` match all characters but slashes.
+ # '*.pyc': matches 'test.pyc' and 'pkg/test.pyc'
+ # 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc'
+ # '.svn': matches 'pkg/.svn' and all of its children
+ # 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o'
+ # 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o'
+ prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject',
+ '.hg', '.svn', '_svn', '.git']
+
+ # Specifies which files should be considered python files. It is
+ # useful when you have scripts inside your project. Only files
+ # ending with ``.py`` are considered to be python files by
+ # default.
+ #prefs['python_files'] = ['*.py']
+
+ # Custom source folders: By default rope searches the project
+ # for finding source folders (folders that should be searched
+ # for finding modules). You can add paths to that list. Note
+ # that rope guesses project source folders correctly most of the
+ # time; use this if you have any problems.
+ # The folders should be relative to project root and use '/' for
+ # separating folders regardless of the platform rope is running on.
+ # 'src/my_source_folder' for instance.
+ #prefs.add('source_folders', 'src')
+
+ # You can extend python path for looking up modules
+ #prefs.add('python_path', '~/python/')
+
+ # Should rope save object information or not.
+ prefs['save_objectdb'] = True
+ prefs['compress_objectdb'] = False
+
+ # If `True`, rope analyzes each module when it is being saved.
+ prefs['automatic_soa'] = True
+ # The depth of calls to follow in static object analysis
+ prefs['soa_followed_calls'] = 0
+
+ # If `False` when running modules or unit tests "dynamic object
+ # analysis" is turned off. This makes them much faster.
+ prefs['perform_doa'] = True
+
+ # Rope can check the validity of its object DB when running.
+ prefs['validate_objectdb'] = True
+
+ # How many undos to hold?
+ prefs['max_history_items'] = 32
+
+ # Shows whether to save history across sessions.
+ prefs['save_history'] = True
+ prefs['compress_history'] = False
+
+ # Set the number spaces used for indenting. According to
+ # :PEP:`8`, it is best to use 4 spaces. Since most of rope's
+ # unit-tests use 4 spaces it is more reliable, too.
+ prefs['indent_size'] = 4
+
+ # Builtin and c-extension modules that are allowed to be imported
+ # and inspected by rope.
+ prefs['extension_modules'] = []
+
+ # Add all standard c-extensions to extension_modules list.
+ prefs['import_dynload_stdmods'] = True
+
+ # If `True` modules with syntax errors are considered to be empty.
+ # The default value is `False`; When `False` syntax errors raise
+ # `rope.base.exceptions.ModuleSyntaxError` exception.
+ prefs['ignore_syntax_errors'] = False
+
+ # If `True`, rope ignores unresolvable imports. Otherwise, they
+ # appear in the importing namespace.
+ prefs['ignore_bad_imports'] = False
+
+
+def project_opened(project):
+ """This function is called after opening the project"""
+ # Do whatever you like here!
diff --git a/random241.py b/random241.py
new file mode 100755
index 0000000..1f74485
--- /dev/null
+++ b/random241.py
@@ -0,0 +1,63 @@
+#!/usr/bin/python2
+
+import cv
+import time
+import numpy as np
+import logging
+import random241arg as arg
+import random241sensor as sensor
+import random241osc as osc
+
+showStream = False
+stop_key = 0
+capture = True
+camNumber = 1
+time_delta = 60 * 60 / 2
+logging.basicConfig(filename='random241.log',
+ format='%(asctime)s %(message)s',
+ filemode='w', level=logging.INFO)
+
+
+# Read parameters
+params = arg.read_params()
+# Define which cam to use, etc.
+#cam = sensor.capture(params['-c'], showStream)
+
+# Get frame and size information from camera
+cam = cv.CaptureFromCAM(camNumber)
+frame = cv.QueryFrame(cam)
+if frame is not None:
+ frame_size = cv.GetSize(frame)
+ logging.info('Grabbing random numbers from: %dx%dpx.',
+ frame_size[0], frame_size[1])
+
+ # Get matrix with values from frame
+ mat = cv.GetMat(frame)
+ frame_values = np.asarray(mat)
+ # Create grayscale image
+ gray_values = sensor.bgr2gray(frame_values)
+
+ # Define the time to run the test
+ time_delta = time_delta + time.time()
+
+ # Setup OSC
+ osc.connect_to_server("dvzrv", 57120)
+
+ # Main loop for accessing the camera and calculating random numbers from it
+ #while True:
+ while time_delta > time.time():
+ img = cv.QueryFrame(cam)
+ # Get a numpy array with rgb values
+ #frame = sensor.frame_to_mat(stream)
+ randomness = sensor.find_dot(sensor.bgr2gray(sensor.frame_to_mat(img)))
+ if randomness is not None:
+ osc.send_osc_msg_to_server(randomness)
+ if showStream:
+ while stop_key != ord("q"):
+ cv.ShowImage("Americium 241", img)
+ key = cv.WaitKey(2)
+
+ #time.sleep(5)
+ #random241sensor.set_capture(False)
+else:
+ logging.error('Connect camera %d first!', camNumber)
diff --git a/random241arg.py b/random241arg.py
new file mode 100755
index 0000000..4bd00d8
--- /dev/null
+++ b/random241arg.py
@@ -0,0 +1,25 @@
+#!/usr/bin/python2
+
+from sys import argv
+
+
+def read_params():
+ # Checks the given parameters
+ info = """Use the program as following:
+ random241.py [option] <param> ...
+ Options:
+ -c number of cam to use (starts with first found camera 0 (default))
+ -r remote address to send the output to (standard 192.168.0.7)
+ """
+ default = {'-c': "1", '-r': "192.168.0.7"}
+ parameters = default.copy()
+ if len(argv) != 3:
+ for i in xrange(1, len(argv) - 1, 2):
+ if argv[i] in parameters:
+ parameters[argv[i]] = argv[i + 1]
+ else:
+ print info
+ return 0
+ return parameters
+ else:
+ return default
diff --git a/random241osc.py b/random241osc.py
new file mode 100755
index 0000000..3d95f69
--- /dev/null
+++ b/random241osc.py
@@ -0,0 +1,31 @@
+#import OSC as osc
+import liblo as osc
+import logging
+
+# Declare an empty target
+target = None
+
+
+# Connect to the server
+def connect_to_server(hostname, port):
+ global target
+ if (hostname or port) is None:
+ target = osc.Adress('127.0.0.1', 57120, osc.TCP)
+ else:
+ try:
+ target = osc.Address(hostname, port, osc.TCP)
+ except osc.AddressError, err:
+ logging.error(err)
+
+
+# Send a osc_message to the server
+def send_osc_msg_to_server(randomness):
+ global target
+ # if the message is not empty and longer than 1
+ if randomness is not None and len(randomness) > 1:
+ msg = osc.Message("/random")
+ msg.add(randomness[0], randomness[1])
+ try:
+ osc.send(target, msg)
+ except:
+ logging.error('OSC: Sending of message failed.')
diff --git a/random241sensor.py b/random241sensor.py
new file mode 100755
index 0000000..624cc29
--- /dev/null
+++ b/random241sensor.py
@@ -0,0 +1,157 @@
+#!/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 = 30.0
+checked = np.zeros((1, 1), dtype=np.int)
+mat = np.zeros((1, 1))
+clusters = []
+
+
+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 find_dot(mat_input):
+ global mat
+ global checked
+ global clusters
+ 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[:]
+ return balance_point
+ 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]
+
+
+# TODO: Function to add up balances
+# TODO: Function to calculate forced balance