Adds mouse_point function to library

Implements mouse_pos function
Implements corresponding tests
Two modes included, single and multiple. 

TODO:
How to tests functions needing user inputs? 

Signed-off-by: Julien Lengrand-Lambert <julien@lengrandlambert.fr>
This commit is contained in:
Julien Lengrand-Lambert
2011-11-27 23:05:41 +01:00
parent 2a6dc49ff3
commit f6d9b0b047
4 changed files with 97 additions and 2 deletions

View File

@@ -11,6 +11,77 @@ Created on Nov 19, 2011
import sys
import cv
_mouse_pos = []
def _on_mouse(event, x, y, flags, param):
"""
None = onMouse(event, x, y, flags, param)
Function automatically called by opencv when having mouse events on a
displayed frame. In here, we are searching for a left mouse click
"""
global _mouse_pos
if event == cv.CV_EVENT_LBUTTONDOWN :
_mouse_pos.append((x, y))
def mouse_point(img, name="Mouse Points", mode="S"):
"""
Displays input image and waits for user click on a point of the image.
For each click, the (x, y) coordinates are retrieved.
Two modes are possible:
-Single :
The function exits automatically on first click.
Returns a list containing 1 (x,y) tuple.
-Multiple :
All clicks are saved. The function exists when the user types on keyboard
Returns containing (x,y) tuples.
---
Ex:
img = cv.LoadImage("../data/tippy.jpg", cv.CV_LOAD_IMAGE_GRAYSCALE)
mouse_points(img, name="mouse points", mode="S")
"""
if not isinstance(name, str):
raise TypeError("(%s) Name :String expected!" % (sys._getframe().f_code.co_name))
if not isinstance(mode, str):
raise TypeError("(%s) Mode :String expected!" % (sys._getframe().f_code.co_name))
global _mouse_pos
cv.StartWindowThread()
cv.NamedWindow(name, cv.CV_WINDOW_AUTOSIZE)
cv.SetMouseCallback(name, _on_mouse)
try :
cv.ShowImage(name, img)
except TypeError:
raise TypeError("(%s) img : IplImage expected!" % (sys._getframe().f_code.co_name))
if mode == "S":
_single_point()
elif mode == "M":
_multiple_points()
else:
raise ValueError("(%s) Mode can be either S (single) or M (multiple)" % (sys._getframe().f_code.co_name))
cv.DestroyWindow(name)
return _mouse_pos
def _single_point():
"""
Internal function, used in mouse_point
"""
while(len(_mouse_pos) == 0):
cv.WaitKey(10)
def _multiple_points():
"""
Internal function, used in mouse_point
"""
char = -1
while (char == -1):
char = cv.WaitKey(10)
# ----
def create_same_image(in_img, zero=0):
"""
Creates an image of same size, depth and number of channels as input image
@@ -31,4 +102,6 @@ def create_same_image(in_img, zero=0):
if zero:
cv.Zero(out_img)
return out_img
return out_img

View File

@@ -20,6 +20,11 @@ def simple_region_growing(img, seed, threshold=1):
Outputs a single channel 8 bits binary (0 or 255) image. Extracted region is highlighted in white.
"""
try:
dims = cv.GetSize(img)
except TypeError:
raise TypeError("(%s) img : IplImage expected!" % (sys._getframe().f_code.co_name))
# img test
if not(img.depth == cv.IPL_DEPTH_8U):
raise TypeError("(%s) 8U image expected!" % (sys._getframe().f_code.co_name))
@@ -34,7 +39,7 @@ def simple_region_growing(img, seed, threshold=1):
if not((isinstance(seed, tuple)) and (len(seed) is 2) ) :
raise TypeError("(%s) (x, y) variable expected!" % (sys._getframe().f_code.co_name))
dims = cv.GetSize(img)
if (seed[0] or seed[1] ) < 0 :
raise ValueError("(%s) Seed should have positive values!" % (sys._getframe().f_code.co_name))
elif ((seed[0] > dims[0]) or (seed[1] > dims[1])):

View File

@@ -24,6 +24,11 @@ class Test(unittest.TestCase):
self.img_3c = cv.LoadImage("../data/tippy.jpg", cv.CV_LOAD_IMAGE_COLOR) # 3 channel image
self.img_fake_2c = cv.CreateImage((15, 15), cv.IPL_DEPTH_8U, 2) # 2 channels
self.fake_img = 10 # non Image
self.false_mode = "A" # non True/False (or 0/1) argument
self.fake_mode = 100 # non True/False (or 0/1) argument
self.fake_name = 100 # non True/False (or 0/1) argument
def tearDown(self):
"""
This method is called after each test
@@ -40,5 +45,15 @@ class Test(unittest.TestCase):
self.assertEqual(cv.GetSize(img), cv.GetSize(out_img))
self.assertRaises(TypeError, lambda: bo.create_same_image(self.fake_img))
def test_mouse_point(self):
# img test
self.assertRaises(TypeError, lambda: bo.mouse_point(self.fake_img))
# name test
self.assertRaises(TypeError, lambda: bo.mouse_point(self.fake_name))
# mode test
self.assertRaises(TypeError, lambda: bo.mouse_point(self.fake_mode))
self.assertRaises(ValueError, lambda: bo.mouse_point(self.false_mode))
# TODO: How to test arguments that need user interaction?
#if __name__ == "__main__":
#unittest.main()

View File

@@ -44,6 +44,8 @@ class Test(unittest.TestCase):
# Image type tests
self.assertRaises(TypeError, lambda: se.simple_region_growing(self.img_3c, self.seed))
self.assertRaises(TypeError, lambda: se.simple_region_growing(self.img_16s, self.seed))
self.assertRaises(TypeError, lambda: se.simple_region_growing(self.fake_img, self.seed))
# Threshold tests
self.assertRaises(ValueError, lambda: se.simple_region_growing(self.img_1c, self.seed, self.neg_thres))
self.assertRaises(TypeError, lambda: se.simple_region_growing(self.img_1c, self.seed, self.bad_thres))