diff --git a/documentation/mask.md b/documentation/mask.md new file mode 100644 index 0000000..2bf7a4c --- /dev/null +++ b/documentation/mask.md @@ -0,0 +1,12 @@ +# Editing Masks +`masktest.py` is used to set mask values which are stored in `colors.txt`. Put the image you want to calibrate to in the `images` folder. Then run `python3 masktest.py filename.png`. Press `esc` to exit the program. +### Adjusting Mask Values +The sliders adjust the range of colors in the mask using HLS color space. To load a color from the calibration image, double click a specific point of the calibration image. This will set the mask values to the color selected. +### Saving a Mask +To save a mask, type `s`, then type the name of the color in the command line and hit enter. +### Loading a Mask +To load a mask, type `l` , then type the name of the color in the command line and hit enter. + +# Using Masks +Use `from mask import colors` in your python file to use masks. To get a mask for an image use `colors.get_mask('color', image)` where `'color'` is a string of the color you are masking for and `image` is the cv2 image in RGB color space. +If your python file is located at `vision/folder/file.py` you must run it from the `vision` folder using `python3 -m folder.file`. diff --git a/vision/mask/__init__.py b/vision/mask/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/vision/mask/colors.py b/vision/mask/colors.py new file mode 100644 index 0000000..0b7a6f9 --- /dev/null +++ b/vision/mask/colors.py @@ -0,0 +1,42 @@ +import numpy as np +import json +from enum import Enum +import cv2 +import pkgutil + +def get_data(): + data = pkgutil.get_data(__name__, "colors.txt") + json_data = json.loads(data.decode()) + return json_data + + +def set_color(color, lower, upper): + with open('colors.txt', 'r') as file: + colors = json.load(file) + colors[color] = [lower, upper] + with open('colors.txt', 'w') as outfile: + json.dump(colors, outfile) + +def get_mask(color, image): + hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HLS) + colors = get_data() + lower, upper = colors[color] + return cv2.inRange(hsv, np.array(lower), np.array(upper)) + +def get_values(color): + colors = get_data() + return colors[color] + +def grid_lines(image): + red = get_mask('red', image) + blue = get_mask('blue', image) + mask = cv2.bitwise_not(cv2.bitwise_or(red, blue)) + kernel = np.ones((15, 15), np.uint8) + eroded = cv2.erode(mask, kernel) + + grey = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) + thresh = cv2.adaptiveThreshold(grey, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 7, 6) + + threshAndMask = cv2.bitwise_and(thresh, eroded) + + return threshAndMask \ No newline at end of file diff --git a/vision/mask/colors.txt b/vision/mask/colors.txt new file mode 100644 index 0000000..c335b06 --- /dev/null +++ b/vision/mask/colors.txt @@ -0,0 +1 @@ +{"blue": [[86, 33, 184], [126, 255, 255]], "red": [[149, 11, 55], [180, 184, 255]], "black": [[29, 0, 0], [62, 255, 255]], "a": [[0, 0, 0], [180, 255, 255]], "purple": [[153, 59, 38], [180, 255, 176]], "yellow": [[0, 74, 110], [39, 208, 255]], "\u001b\u001becloikqwertyuiopasdfghjklzxcvbnm,./1234567890098765456": [[0, 74, 110], [39, 208, 255]]} \ No newline at end of file diff --git a/vision/mask/images/transect.png b/vision/mask/images/transect.png new file mode 100644 index 0000000..dce3cee Binary files /dev/null and b/vision/mask/images/transect.png differ diff --git a/vision/mask/masktest.py b/vision/mask/masktest.py new file mode 100644 index 0000000..905adc4 --- /dev/null +++ b/vision/mask/masktest.py @@ -0,0 +1,97 @@ +import cv2 +import numpy as np +import imutils +import colors +import argparse + +SIZE = 650 + +def nothing(x): + pass + +THRESH = 20 +def loadPixel(event, x, y, flags, param): + if event == cv2.EVENT_LBUTTONDBLCLK: + x = int((float(width) / SIZE) * x) + y = int((float(width) / SIZE) * y) + h, s, v = hsv[y][x] + + cv2.setTrackbarPos('H1', 'image', h - THRESH) + cv2.setTrackbarPos('S1', 'image', s - THRESH) + cv2.setTrackbarPos('V1', 'image', v - THRESH) + cv2.setTrackbarPos('H2', 'image', h + THRESH) + cv2.setTrackbarPos('S2', 'image', s + THRESH) + cv2.setTrackbarPos('V2', 'image', v + THRESH) + +parser = argparse.ArgumentParser() +parser.add_argument('file_name', type=str) +args = parser.parse_args() + +image = cv2.imread('images/' + args.file_name) +hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HLS) +height, width, channels = image.shape + +cv2.namedWindow('image') +cv2.namedWindow('original') +resized = imutils.resize(image, width=SIZE) +cv2.imshow('original', resized) +cv2.setMouseCallback('original', loadPixel) +cv2.createButton('test', loadPixel) + +# create trackbars for color change +cv2.createTrackbar('H1','image',0,180,nothing) +cv2.createTrackbar('H2','image',0,180,nothing) +cv2.createTrackbar('S1','image',0,255,nothing) +cv2.createTrackbar('S2','image',0,255,nothing) +cv2.createTrackbar('V1','image',0,255,nothing) +cv2.createTrackbar('V2','image',0,255,nothing) + +cv2.setTrackbarPos('H2', 'image', 180) +cv2.setTrackbarPos('S2', 'image', 255) +cv2.setTrackbarPos('V2', 'image', 255) + + + +while(1): + k = cv2.waitKey(1) & 0xFF + if k == 27: + break + elif k == 115: + color = input("Set color: ") + colors.set_color(color, [h1, s1, v1], [h2, s2, v2]) + elif k == 108: + color = input("Load color: ") + lower, upper = colors.get_values(color) + h1, s1, v1 = lower + h2, s2, v2 = upper + cv2.setTrackbarPos('H1', 'image', h1) + cv2.setTrackbarPos('L1', 'image', s1) + cv2.setTrackbarPos('S1', 'image', v1) + cv2.setTrackbarPos('H2', 'image', h2) + cv2.setTrackbarPos('L2', 'image', s2) + cv2.setTrackbarPos('S2', 'image', v2) + + # get current positions of four trackbars + h1 = cv2.getTrackbarPos('H1','image') + h2 = cv2.getTrackbarPos('H2','image') + s1 = cv2.getTrackbarPos('L1','image') + s2 = cv2.getTrackbarPos('L2','image') + v1 = cv2.getTrackbarPos('S1','image') + v2 = cv2.getTrackbarPos('S2','image') + + lower = np.array([h1, s1, v1]) + upper = np.array([h2, s2, v2]) + + mask = cv2.inRange(hsv, lower, upper) + resized = imutils.resize(mask, width=SIZE) + cv2.imshow('image', resized) + + # gridlines = colors.gridLines(image) + # resized = imutils.resize(gridlines, width=SIZE) + # cv2.imshow('Grid Lines', resized) + + + + + +cv2.destroyAllWindows() \ No newline at end of file