From ca73fcc336edc23db5750e93b6e1014d32a54ea5 Mon Sep 17 00:00:00 2001 From: Hector Fernandez Date: Tue, 29 Sep 2020 13:27:32 +0200 Subject: Added new test to validate video output with a webcam. --- test-cli/test/files/OpenSans-Regular.ttf | Bin 0 -> 217360 bytes test-cli/test/helpers/camara.py | 18 +---- test-cli/test/helpers/detect.py | 61 +++++++++++++++ test-cli/test/helpers/sdl.py | 22 +++--- test-cli/test/scripts/v4l-cam.sh | 14 ++++ test-cli/test/tests/qvideo.py | 124 +++++++++++++++++++++++++++++++ 6 files changed, 214 insertions(+), 25 deletions(-) create mode 100644 test-cli/test/files/OpenSans-Regular.ttf create mode 100644 test-cli/test/helpers/detect.py create mode 100755 test-cli/test/scripts/v4l-cam.sh create mode 100644 test-cli/test/tests/qvideo.py (limited to 'test-cli') diff --git a/test-cli/test/files/OpenSans-Regular.ttf b/test-cli/test/files/OpenSans-Regular.ttf new file mode 100644 index 0000000..db43334 Binary files /dev/null and b/test-cli/test/files/OpenSans-Regular.ttf differ diff --git a/test-cli/test/helpers/camara.py b/test-cli/test/helpers/camara.py index 9b2829c..afe8112 100644 --- a/test-cli/test/helpers/camara.py +++ b/test-cli/test/helpers/camara.py @@ -1,8 +1,7 @@ import cv2 -from test.helpers.syscmd import SysCommand +import sh class Camara(object): - __parent = None __device_name = None __device = None __w = 1280 @@ -13,8 +12,7 @@ class Camara(object): __hue = 0.0 __exposure = 166 - def __init__(self, parent, device="video0", width=1280, height=720): - self.__parent = parent + def __init__(self, device="video0", width=1280, height=720): self.__device_name = device self.__w = width self.__h = height @@ -64,21 +62,13 @@ class Camara(object): def __configure(self): self.__w = self.__setCamVar(cv2.CAP_PROP_FRAME_WIDTH, self.__w) self.__h = self.__setCamVar(cv2.CAP_PROP_FRAME_HEIGHT, self.__h) - cam_setup = SysCommand('v4lsetup', '{}/scripts/v4l-cam.sh'.format(self.__parent.getAppPath())) - cam_setup.execute() - - #self.__contrast = self.__setCamVar(cv2.CAP_PROP_CONTRAST, self.__contrast) - #self.__brightness = self.__setCamVar(cv2.CAP_PROP_BRIGHTNESS, self.__brightness) - #self.__saturation = self.__setCamVar(cv2.CAP_PROP_SATURATION, self.__saturation) - #self.__hue = self.__setCamVar(cv2.CAP_PROP_HUE, self.__hue) - #self.__exposure = self.__setCamVar(cv2.CAP_PROP_EXPOSURE, self.__exposure) - + sh.bash("../scripts/v4l-cam.sh") def __setCamVar(self, key, val): valold = cv2.VideoCapture.get(self.__device, key) if valold != val: cv2.VideoCapture.set(self.__device, key, val) - t = cv2.VideoCapture.get(self.__device, key) + t = cv2.VideoCapture.get(self.__device, key) return t return val diff --git a/test-cli/test/helpers/detect.py b/test-cli/test/helpers/detect.py new file mode 100644 index 0000000..193dabf --- /dev/null +++ b/test-cli/test/helpers/detect.py @@ -0,0 +1,61 @@ +import cv2 +import numpy as np + + +class Detect_Color(object): + oFrame = None + img_hsv = None + __red_lower1 = [0, 50, 20] + __red_upper1 = [5, 255, 255] + __red_lower2 = [175, 50, 20] + __red_upper2 = [180, 255, 255] + __blue_lower = [110, 50, 50] + __blue_upper = [130, 255, 255] + __green_lower = [36, 25, 25] + __green_upper = [86, 255, 255] + + def __init__(self, frame): + self.oFrame = frame + self.__hist() + + def __hist(self): + self.img_hsv = cv2.cvtColor(self.oFrame, cv2.COLOR_BGR2HSV) + + def getRed(self): + return self.__detect_two_areas([0, 50, 20], [5, 255, 255], [175, 50, 20], [180, 255, 255]) + + def getBlue(self): + return self.__detect_one_area([110, 50, 50], [130, 255, 255]) + + def getGreen(self): + return self.__detect_one_area([36, 25, 25], [86, 255, 255]) + + def __detect_one_area(self, lower, upper): + a_lower = np.array(lower) + a_upper = np.array(upper) + c_mask = cv2.inRange(self.img_hsv, a_lower, a_upper) + croped = cv2.bitwise_and(self.oFrame, self.oFrame, mask=c_mask) + mean_v = cv2.mean(self.oFrame, mask=c_mask) + mean = {} + mean['R'] = mean_v[2] + mean['G'] = mean_v[1] + mean['B'] = mean_v[0] + count = cv2.countNonZero(c_mask) + return c_mask, croped, mean, count + + def __detect_two_areas(self, lower1, upper1, lower2, upper2): + a1_lower = np.array(lower1) + a1_upper = np.array(upper1) + a2_lower = np.array(lower2) + a2_upper = np.array(upper2) + c_mask1 = cv2.inRange(self.img_hsv, a1_lower, a1_upper) + c_mask2 = cv2.inRange(self.img_hsv, a2_lower, a2_upper) + c_mask = cv2.bitwise_or(c_mask1, c_mask2) + croped = cv2.bitwise_and(self.oFrame, self.oFrame, mask=c_mask) + mean_v = cv2.mean(self.oFrame, mask=c_mask) + mean = {} + mean['R'] = mean_v[2] + mean['G'] = mean_v[1] + mean['B'] = mean_v[0] + count = cv2.countNonZero(c_mask) + return c_mask, croped, mean, count diff --git a/test-cli/test/helpers/sdl.py b/test-cli/test/helpers/sdl.py index 8f55d9f..2abb6ee 100644 --- a/test-cli/test/helpers/sdl.py +++ b/test-cli/test/helpers/sdl.py @@ -22,10 +22,10 @@ class SDL2(object): __renderer = None __srender = None - def __init__(self, parent): + def __init__(self): os.environ['SDL_VIDEODRIVER'] = "x11" os.environ['DISPLAY'] = ":0" - self.__resources = sdl2.ext.Resources(parent.getAppPath(), 'files') + # self.__resources = sdl2.ext.Resources(parent.getAppPath(), 'files') sdl2.ext.init() self.__createWindow() @@ -39,8 +39,8 @@ class SDL2(object): self.__window.show() SDL_ShowCursor(SDL_DISABLE) - def createFont(self, fontName, fontSize, fontColor): - return sdl2.ext.FontManager(font_path=self.__resources.get_path(fontName), size=fontSize, color=fontColor) + # def createFont(self, fontName, fontSize, fontColor): + # return sdl2.ext.FontManager(font_path=self.__resources.get_path(fontName), size=fontSize, color=fontColor) def WriteText(self, text, x, y, fontManager): imText = self.__factory.from_text(text, fontmanager=fontManager) @@ -69,16 +69,16 @@ class SDL2(object): def update(self): self.__renderer.present() - def showImage(self, filename): - im = self.__factory.from_image(self.__resources.get_path(filename)) - self.__srender.render(im) + # def showImage(self, filename): + # im = self.__factory.from_image(self.__resources.get_path(filename)) + # self.__srender.render(im) class SDL2_Test(object): __sdl2 = None - def __init__(self, parent): - self.__sdl2 = SDL2(parent) + def __init__(self): + self.__sdl2 = SDL2() def Clear(self): self.__sdl2.fillbgColor('black', True) @@ -93,8 +93,8 @@ class SDL2_Message(object): __fontManager_w = None __fontManager_b = None - def __init__(self, parent): - self.__sdl2 = SDL2(parent) + def __init__(self): + self.__sdl2 = SDL2() self.__fontManager_w = self.__sdl2.createFont('OpenSans-Regular.ttf', 24, Colors['white']) self.__fontManager_b = self.__sdl2.createFont('OpenSans-Regular.ttf', 24, Colors['black']) diff --git a/test-cli/test/scripts/v4l-cam.sh b/test-cli/test/scripts/v4l-cam.sh new file mode 100755 index 0000000..18da1c0 --- /dev/null +++ b/test-cli/test/scripts/v4l-cam.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +v4l2-ctl -d /dev/video0 -c exposure_auto=3 +v4l2-ctl -d /dev/video0 -c brightness=0 +v4l2-ctl -d /dev/video0 -c contrast=20 +v4l2-ctl -d /dev/video0 -c saturation=55 +v4l2-ctl -d /dev/video0 -c hue=0 +v4l2-ctl -d /dev/video0 -c white_balance_temperature_auto=0 +v4l2-ctl -d /dev/video0 -c gamma=100 +v4l2-ctl -d /dev/video0 -c power_line_frequency=1 +v4l2-ctl -d /dev/video0 -c white_balance_temperature=4500 +v4l2-ctl -d /dev/video0 -c sharpness=2 +v4l2-ctl -d /dev/video0 -c backlight_compensation=2 +# v4l2-ctl -d /dev/video0 -c exposure_absolute=166 \ No newline at end of file diff --git a/test-cli/test/tests/qvideo.py b/test-cli/test/tests/qvideo.py new file mode 100644 index 0000000..e2f413e --- /dev/null +++ b/test-cli/test/tests/qvideo.py @@ -0,0 +1,124 @@ +import unittest +import sh +import time +from test.helpers.camara import Camara +from test.helpers.detect import Detect_Color +from test.helpers.sdl import SDL2_Test + +class Qvideo(unittest.TestCase): + params = None + __resultlist = None # resultlist is a python list of python dictionaries + + def __init__(self, testname, testfunc, varlist): + self.params = varlist + super(Qvideo, self).__init__(testfunc) + self._testMethodDoc = testname + self.__xmlObj = varlist["xml"] + self.__QVideoName = varlist.get('name', 'qvideo') + self.__resultlist = [] + self.__Camara = Camara() + self.__SDL2_Test = SDL2_Test() + self.__SDL2_Test.Clear() + + def define_capture(self): + self.__Camara.setSize( + int(self.params.get('capture_size_w', self.__xmlObj.getKeyVal(self.__QVideoName, "capture_size_w", 1280))), + int(self.params.get('capture_size_h', self.__xmlObj.getKeyVal(self.__QVideoName, "capture_size_h", 720)))) + self.__discard_frames_Count = int(self.params.get('capture_discardframes', self.__xmlObj.getKeyVal(self.__QVideoName, "capture_discardframes", 3))) + self.__frame_mean = int(self.params.get('capture_framemean', self.__xmlObj.getKeyVal(self.__QVideoName, "capture_framemean", 3))) + self.__max_failed = int(self.params.get('capture_maxfailed', self.__xmlObj.getKeyVal(self.__QVideoName, "capture_maxfailed", 1))) + + def __drop_frames(self, frame_count): + count = frame_count + while count > 0: + _ = self.__Camara.getFrame() + count -= 1 + + def Verify_Color(self, color): + self.paintColor(color) + count = self.__frame_mean + res_ok = 0 + res_failed = 0 + r_count = 0 + c_mean = 0 + while count > 0: + res, t = self.Capture(color) + if res: + res_ok += 1 + else: + res_failed += 1 + if t == "count": + r_count += 1 + else: + c_mean +=1 + count -= 1 + self.unpaintColor(color) + if res_failed > self.__max_failed: + if r_count > 0: + return '{}_COLOR_FAILED'.format(color) + elif c_mean > 0: + return 'MEAN_{}_FAILED'.format(color) + return "ok" + + def paintColor(self, color): + self.__SDL2_Test.Paint(color) + time.sleep(3) + self.__drop_frames(self.__Camara.getFrameCount()) + + def unpaintColor(self, color): + self.__SDL2_Test.Clear() + time.sleep(1) + + def Capture(self, color): + image = self.__Camara.getFrame() + if image is None: + return None + dtObject = Detect_Color(image) + if color == 'RED': + _, _, mean, count = dtObject.getRed() + elif color == 'BLUE': + _, _, mean, count = dtObject.getBlue() + elif color == 'GREEN': + c_mask, croped, mean, count = dtObject.getGreen() + + return self.checkThreshold(color, mean, count) + + def checkThreshold(self, color, mean, count): + min_count = int( + self.params.get('{}_min_count'.format(color), + self.__xmlObj.getKeyVal(self.__QVideoName, '{}_min_count'.format(color), 50000))) + + str = "" + # first verify count + if count >= min_count: + return True, "" + else: + str = "count" + return False, str + + def execute(self): + self.__resultlist = [] + + # set image size + self.define_capture() + # Open camara + if not self.__Camara.Open(): + self.fail('Error: USB camera not found') + # discard initial frames + self.__drop_frames(self.__discard_frames_Count) + # Test + res = self.Verify_Color('RED') + if res != "ok": + self.fail("failed: RED verification failed") + res = self.Verify_Color('BLUE') + if res != "ok": + self.fail("failed: BLUE verification failed") + res = self.Verify_Color('GREEN') + if res != "ok": + self.fail("failed: GREEN verification failed") + + def getresults(self): + return self.__resultlist + + def gettextresult(self): + return "" -- cgit v1.1