├── .gitignore ├── README.md ├── detect_oven_status.py ├── images ├── oven_off.jpg └── oven_on.jpg └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # PyInstaller 27 | # Usually these files are written by a python script from a template 28 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 29 | *.manifest 30 | *.spec 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .coverage.* 41 | .cache 42 | nosetests.xml 43 | coverage.xml 44 | *,cover 45 | 46 | # Translations 47 | *.mo 48 | *.pot 49 | 50 | # Django stuff: 51 | *.log 52 | 53 | # Sphinx documentation 54 | docs/_build/ 55 | 56 | # PyBuilder 57 | target/ 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Detect oven status - OpenCV light detection 2 | -------------------------------------------------------------------------------- /detect_oven_status.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import argparse 4 | import numpy as np 5 | import cv2 6 | 7 | def create_hue_mask(image, lower_color, upper_color): 8 | lower = np.array(lower_color, np.uint8) 9 | upper = np.array(upper_color, np.uint8) 10 | 11 | # Create a mask from the colors 12 | mask = cv2.inRange(image, lower, upper) 13 | output_image = cv2.bitwise_and(image, image, mask = mask) 14 | return output_image 15 | 16 | def main(): 17 | parser = argparse.ArgumentParser(description='Process some integers.') 18 | parser.add_argument("-i", "--image_path", dest = 'image_path', required = True) 19 | parser.add_argument("-o", "--output_dir", dest = 'output_dir', required = False) 20 | 21 | args = parser.parse_args() 22 | 23 | # Load image 24 | image = cv2.imread(args.image_path) 25 | 26 | # Blur image to make it easier to detect objects 27 | blur_image = cv2.medianBlur(image, 3) 28 | if args.output_dir: 29 | result_image_path = os.path.join(args.output_dir, "blur_image.jpg") 30 | cv2.imwrite(result_image_path, blur_image) 31 | 32 | # Convert to HSV in order to 33 | hsv_image = cv2.cvtColor(blur_image, cv2.COLOR_BGR2HSV) 34 | if args.output_dir: 35 | result_image_path = os.path.join(args.output_dir, "hsv_image.jpg") 36 | cv2.imwrite(result_image_path, hsv_image) 37 | 38 | # Get lower red hue 39 | lower_red_hue = create_hue_mask(hsv_image, [0, 100, 100], [10, 255, 255]) 40 | if args.output_dir: 41 | result_image_path = os.path.join(args.output_dir, "lower_red_hue.jpg") 42 | cv2.imwrite(result_image_path, lower_red_hue) 43 | 44 | # Get higher red hue 45 | higher_red_hue = create_hue_mask(hsv_image, [160, 100, 100], [179, 255, 255]) 46 | if args.output_dir: 47 | result_image_path = os.path.join(args.output_dir, "higher_red_hue.jpg") 48 | cv2.imwrite(result_image_path, higher_red_hue) 49 | 50 | # Merge the images 51 | full_image = cv2.addWeighted(lower_red_hue, 1.0, higher_red_hue, 1.0, 0.0) 52 | if args.output_dir: 53 | result_image_path = os.path.join(args.output_dir, "full_image.jpg") 54 | cv2.imwrite(result_image_path, full_image) 55 | 56 | # Blur the final image to reduce noise from image 57 | full_image = cv2.GaussianBlur(full_image, (9, 9), 2, 2) 58 | if args.output_dir: 59 | result_image_path = os.path.join(args.output_dir, "full_image_blur.jpg") 60 | cv2.imwrite(result_image_path, full_image) 61 | 62 | # Convert image to gray in order to find circles in the image 63 | image_gray = cv2.cvtColor(full_image, cv2.COLOR_BGR2GRAY) 64 | if args.output_dir: 65 | result_image_path = os.path.join(args.output_dir, "full_image_gray.jpg") 66 | cv2.imwrite(result_image_path, image_gray) 67 | 68 | # Find circles in the image 69 | circles = cv2.HoughCircles(image_gray, cv2.HOUGH_GRADIENT, 1.2, 100) 70 | 71 | # If we didn't find circles, the oven status is "OFF" 72 | if circles is None: 73 | print "Oven is OFF" 74 | return 75 | 76 | # If we did find circles, the oven is "ON" 77 | print "Oven is ON" 78 | 79 | if args.output_dir: 80 | # Draw the circles on the original image 81 | circles = np.round(circles[0, :]).astype("int") 82 | for (center_x, center_y, radius) in circles: 83 | cv2.circle(image, (center_x, center_y), radius, (0, 255, 0), 4) 84 | result_image_path = os.path.join(args.output_dir, "original_image_with_circles.jpg") 85 | cv2.imwrite(result_image_path, image) 86 | 87 | if __name__ == '__main__': 88 | main() 89 | -------------------------------------------------------------------------------- /images/oven_off.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazuar/opencv_light_detection/db83b541e1992ef264b90c111b38771d8243cebc/images/oven_off.jpg -------------------------------------------------------------------------------- /images/oven_on.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazuar/opencv_light_detection/db83b541e1992ef264b90c111b38771d8243cebc/images/oven_on.jpg -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | numpy==1.9.2 2 | --------------------------------------------------------------------------------