├── README.md ├── colorspace_condition.py ├── using_colorspaces.py ├── using_colorspaces_with_condition.py └── with_PiCamera.py /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | *basic-flame-detection* 4 | 5 | Detect flames in video or static image frames using image processing 6 | 7 | **using_colorspaces.py uses thresholding on different colorspaces to detect possible flame pixels 8 | **colorspace_condition.py uses basic RGB and YUV color model condition for each pixel in an image to filter possible flame pixels 9 | **with_PiCamera.py takes video feed from a Raspberry Pi's Pi Camera module and detects flames in image frames using colorspace thresholding algorithm from using_colorspaces.py_ 10 | **using_colorspaces_with_condition.py uses thresholding and also R>G>B and Y>Cr>Cb condition to narrow down pixels, thereby decreasing false positives. 11 | !!! THE THRESHOLDS IN using_colorspaces.py and using_colorspaces_with_condition.py ARE DIFFERENT!!! 12 | This was done because of experimental threshold findings in different conditions. 13 | 14 | *using_colorspaces_with_condition.py might will give better results than using_colorspaces.py 15 | 16 | *Image Frame should be given as the first argument after script names ( expect for with_PiCamera.py) 17 | 18 | [Does give false positives] #reduced in using_colorspaces_with_condition.py 19 | NOTE that this is also because of change in threshold values and not just because of additional condition 20 | 21 | ---Tweaking the threshold values or adding more ranges and bitwise logic to enable more accurate detection in varying types of images is encouraged 22 | 23 | ---colorspace_condition.py is ideally to be included as a condition in using_colorspaces.py 24 | 25 | ---The framerate and video resolution in with_PiCamera.py can be changed as per user's choice and Pi's performance 26 | -------------------------------------------------------------------------------- /colorspace_condition.py: -------------------------------------------------------------------------------- 1 | #author: Avadhoot S 2 | """ 3 | Basic conditions in many research papers for flame detection is 4 | R > G > B in RGB color model 5 | and 6 | Y > Cr > Cb in YUV color model 7 | this program checks both(AND logic) of conditions in an image 8 | """ 9 | import cv2 10 | import matplotlib.pyplot as plt 11 | import numpy as np 12 | import sys 13 | 14 | #image acquisition 15 | img = cv2.cvtColor(cv2.imread(str(sys.argv[1]), -1), cv2.COLOR_BGR2RGB) #in RGB 16 | image = img.copy() #create copy of image 17 | 18 | #r > g > b 19 | id_rg = (image[:, :, 0] > image[:, :, 1]) # r > g 20 | id_gb = (image[:, :, 1] > image[:, :, 2]) # g > b 21 | id_rb = (image[:, :, 0] > image[:, :, 2]) # r > b 22 | id_rgb_ = np.bitwise_and(id_rg, id_gb) 23 | id_rgb = np.bitwise_and(id_rgb_, id_rb) 24 | 25 | #convert to ycrcb format 26 | image_ = cv2.cvtColor(img, cv2.COLOR_RGB2YCR_CB) 27 | 28 | #y > cr > cb 29 | id_ycr = (image_[:, :, 0] > image_[:, :, 1]) # y > cr 30 | id_crcb = (image_[:, :, 1] > image_[:, :, 2]) # cr > cb 31 | id_ycb = (image_[:, :, 0] > image_[:, :, 2]) # y > cb 32 | id_ycrcb_ = np.bitwise_and(id_ycr, id_crcb) 33 | id_ycrcb = np.bitwise_and(id_ycrcb_, id_ycb) 34 | 35 | #r>g>b AND y>cr>cb 36 | id_both = np.bitwise_and(id_rgb, id_ycrcb) #combining using AND logic 37 | 38 | #blacking out rest of the pixels 39 | image[id_both == 0] = [0, 0, 0] 40 | 41 | #display results 42 | plt.subplot(121), plt.imshow(img) 43 | plt.title('Original') 44 | plt.subplot(122), plt.imshow(image) 45 | plt.title('Result') 46 | plt.show() 47 | -------------------------------------------------------------------------------- /using_colorspaces.py: -------------------------------------------------------------------------------- 1 | #author: Avadhoot S 2 | """ 3 | program for detecting flames in image frames 4 | using three colorspace thresholding 5 | threshold values obtained using experimentation and are not universal 6 | adaptive thresholding is suggested for eliminating false positives 7 | """ 8 | import cv2 #opencv2 9 | import numpy as np 10 | import matplotlib.pyplot as plt 11 | import sys 12 | 13 | frame = cv2.cvtColor(cv2.imread(str(sys.argv[1]), -1), cv2.COLOR_BGR2RGB) #standard bgr converted to rgb beforehand 14 | 15 | #median blurring frame 16 | #frame = cv2.medianBlur(frame, 3) 17 | 18 | #ycbcr thresholding 19 | framey = cv2.cvtColor(frame, cv2.COLOR_RGB2YCR_CB) #rgb to ycrcb conversion 20 | 21 | lower_y = np.array([230,120,60]) 22 | upper_y = np.array([300,300,150]) 23 | thres_mask_y1 = cv2.inRange(framey, lower_y, upper_y) #obtaining binary 24 | #bit_mask_y1 = cv2.bitwise_and(framey, framey, mask= thres_mask_y1) 25 | 26 | lower_y2 = np.array([130,180,30]) 27 | upper_y2 = np.array([230,200,90]) 28 | thres_mask_y2 = cv2.inRange(framey, lower_y2, upper_y2) #obtaining binary 29 | #bit_mask_y2 = cv2.bitwise_and(framey, framey, mask= thres_mask_y2) 30 | 31 | thres_mask_y = cv2.bitwise_or(thres_mask_y1, thres_mask_y2) 32 | 33 | #obtaining masked image 34 | 35 | #rgb thresholding 36 | lower_red1 = np.array([230,150,40]) 37 | upper_red1 = np.array([300,300,150]) 38 | thres_mask_red1 = cv2.inRange(frame, lower_red1, upper_red1) 39 | #bit_mask_rgb1 = cv2.bitwise_and(frame, frame, mask= thres_mask_red) 40 | 41 | lower_red2 = np.array([200,90,40]) 42 | upper_red2 = np.array([240,120,80]) 43 | thres_mask_red2 = cv2.inRange(frame, lower_red2, upper_red2) 44 | #bit_mask_rgb2 = cv2.bitwise_and(frame, frame, mask= thres_mask_red) 45 | 46 | thres_mask_red = cv2.bitwise_or(thres_mask_red1, thres_mask_red2) 47 | 48 | #hsv thresholding 49 | hsv_edit = cv2.cvtColor(frame, cv2.COLOR_RGB2HSV).astype(np.uint8) 50 | 51 | lower_blue = np.array([4,100,255]) 52 | upper_blue = np.array([70,300,300]) 53 | thres_mask_hsv = cv2.inRange(hsv_edit, lower_blue, upper_blue) 54 | #bit_mask_hsv = cv2.bitwise_and(frame,frame, mask= thres_mask) 55 | 56 | #mask 57 | thres_mask_hsvnrgb = cv2.bitwise_or(thres_mask_hsv, thres_mask_red) 58 | bit_mask_three = cv2.bitwise_and(thres_mask_hsvnrgb, thres_mask_y) 59 | 60 | #decision making regarding detection 61 | n = cv2.countNonZero(bit_mask_three) 62 | c = 0 63 | if float(n)/float(frame.size) > 0.0005: #need to change 64 | c = 1 65 | 66 | #displaying results 67 | plt.subplot(121), plt.imshow(frame) 68 | plt.title('frame'), plt.xticks([]), plt.yticks([]) 69 | plt.subplot(122),plt.imshow(bit_mask_three) 70 | plt.title('res_mix'), plt.xticks([]), plt.yticks([]) 71 | 72 | if c==1: 73 | plt.figtext(.02, .02, "FLAME DETECTED\n", style='italic', bbox={'facecolor':'red', 'alpha':0.5, 'pad':10}) 74 | else: 75 | plt.figtext(.02, .02, "FLAME NOT DETECTED\n", style='italic', bbox={'facecolor':'green', 'alpha':0.5, 'pad':10}) 76 | 77 | plt.show() 78 | 79 | -------------------------------------------------------------------------------- /using_colorspaces_with_condition.py: -------------------------------------------------------------------------------- 1 | #author: Avadhoot S 2 | """ 3 | program for detecting flames in image frames 4 | using three colorspace thresholding 5 | threshold values obtained using experimentation and are not universal 6 | adaptive thresholding is suggested for eliminating false positives 7 | """ 8 | import cv2 #opencv2 9 | import numpy as np 10 | import matplotlib.pyplot as plt 11 | import sys 12 | 13 | frame = cv2.cvtColor(cv2.imread(str(sys.argv[1]), -1), cv2.COLOR_BGR2RGB) #standard bgr converted to rgb beforehand 14 | 15 | median blurring frame 16 | frame = cv2.medianBlur(frame, 2) 17 | 18 | #ycrcb thresholding 19 | framey = cv2.cvtColor(frame, cv2.COLOR_RGB2YCR_CB) #rgb to ycrcb conversion 20 | 21 | lower_y = np.array([230,120,60]) 22 | upper_y = np.array([300,300,100]) 23 | thres_mask_y1 = cv2.inRange(framey, lower_y, upper_y) #obtaining binary 24 | #bit_mask_y1 = cv2.bitwise_and(framey, framey, mask= thres_mask_y1) 25 | 26 | lower_y2 = np.array([130,180,30]) 27 | upper_y2 = np.array([230,200,150]) 28 | thres_mask_y2 = cv2.inRange(framey, lower_y2, upper_y2) #obtaining binary 29 | #bit_mask_y2 = cv2.bitwise_and(framey, framey, mask= thres_mask_y2) 30 | 31 | thres_mask_y = cv2.bitwise_or(thres_mask_y1, thres_mask_y2) 32 | id_ycr = (framey[:, :, 0] > framey[:, :, 1]) # y > cr 33 | id_crcb = (framey[:, :, 1] > framey[:, :, 2]) # cr > cb 34 | id_ycb = (framey[:, :, 0] > framey[:, :, 2]) # y > cb 35 | id_ycrcb_ = np.bitwise_and(id_ycr, id_crcb) 36 | id_ycrcb = np.bitwise_and(id_ycrcb_, id_ycb) 37 | 38 | thres_mask_y[id_ycrcb == 0] = [0] #obtaining masked image 39 | 40 | #rgb thresholding 41 | lower_red1 = np.array([230,200,40]) 42 | upper_red1 = np.array([255,255,255]) 43 | thres_mask_red1 = cv2.inRange(frame, lower_red1, upper_red1) 44 | #bit_mask_rgb1 = cv2.bitwise_and(frame, frame, mask= thres_mask_red) 45 | 46 | lower_red2 = np.array([200,90,40]) 47 | upper_red2 = np.array([240,120,80]) 48 | thres_mask_red2 = cv2.inRange(frame, lower_red2, upper_red2) 49 | #bit_mask_rgb2 = cv2.bitwise_and(frame, frame, mask= thres_mask_red) 50 | 51 | thres_mask_red = cv2.bitwise_or(thres_mask_red1, thres_mask_red2) 52 | id_rg = (frame[:, :, 0] > frame[:, :, 1]) # r > g 53 | id_gb = (frame[:, :, 1] > frame[:, :, 2]) # g > b 54 | id_rb = (frame[:, :, 0] > frame[:, :, 2]) # r > b 55 | id_rgb_ = np.bitwise_and(id_rg, id_gb) 56 | id_rgb = np.bitwise_and(id_rgb_, id_rb) 57 | #id_max = (frame[:, :, 2] == [255]) 58 | #apply the above condition to the mask 59 | thres_mask_red[id_rgb == 0] = [0] 60 | #thres_mask_red[id_max == 0] = [0] 61 | 62 | 63 | #hsv thresholding 64 | hsv_edit = cv2.cvtColor(frame, cv2.COLOR_RGB2HSV).astype(np.uint8) 65 | 66 | lower_blue = np.array([4,100,220]) 67 | upper_blue = np.array([25,260,260]) 68 | thres_mask_hsv1 = cv2.inRange(hsv_edit, lower_blue, upper_blue) 69 | 70 | lower_blue2 = np.array([50,100,220]) 71 | upper_blue2 = np.array([70,260,260]) 72 | thres_mask_hsv2 = cv2.inRange(hsv_edit, lower_blue2, upper_blue2) 73 | 74 | thres_mask_hsv = cv2.bitwise_or(thres_mask_hsv1, thres_mask_hsv2) 75 | 76 | #mask 77 | #thres_mask_hsvnrgb = cv2.bitwise_or(thres_mask_hsv, thres_mask_red) 78 | #bit_mask_three = cv2.bitwise_and(thres_mask_hsvnrgb, thres_mask_y) 79 | thres_mask_ynrgb = cv2.bitwise_or(thres_mask_y, thres_mask_red) 80 | bit_mask_three = cv2.bitwise_and(thres_mask_ynrgb, thres_mask_hsv) 81 | flame_mask = cv2.bitwise_and(frame, frame, mask = bit_mask_three) 82 | 83 | 84 | #decision making regarding detection 85 | n = cv2.countNonZero(bit_mask_three) 86 | c = 0 87 | pixel_thres = float(n)/float(frame.size) 88 | if pixel_thres > 0.0005: #need to change 89 | c = 1 90 | 91 | #displaying results 92 | plt.subplot(121), plt.imshow(frame) 93 | plt.title('frame'), plt.xticks([]), plt.yticks([]) 94 | plt.subplot(122),plt.imshow(flame_mask) 95 | plt.title('res_mix'), plt.xticks([]), plt.yticks([]) 96 | plt.figtext(0.7, 0.02, "Pixel Threshold count: "+str(pixel_thres), style='italic', bbox={'facecolor':'blue', 'alpha':0.7, 'pad':10}) 97 | mng = plt.get_current_fig_manager() 98 | mng.resize(*mng.window.maxsize()) 99 | 100 | 101 | if c==1: 102 | plt.figtext(.02, .02, "FLAME DETECTED\n", style='italic', bbox={'facecolor':'red', 'alpha':0.5, 'pad':10}) 103 | else: 104 | plt.figtext(.02, .02, "FLAME NOT DETECTED\n", style='italic', bbox={'facecolor':'green', 'alpha':0.5, 'pad':10}) 105 | 106 | plt.show() 107 | 108 | 109 | -------------------------------------------------------------------------------- /with_PiCamera.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import cv2 3 | import matplotlib.pyplot as plt 4 | from picamera.array import PiRGBArray 5 | from picamera import PiCamera 6 | import time 7 | 8 | 9 | #initialise camera, set parameters and capture buffer 10 | cam = PiCamera() 11 | cam.framerate = 6 12 | cam.resolution = (640, 480) 13 | raw_feed = PiRGBArray(cam, size=(640, 480)) 14 | 15 | #time needed for camera to adapt 16 | time.sleep(0.2) #increase or decrease depending on frame rate 17 | 18 | 19 | # capture frames 20 | for feed in cam.capture_continuous(raw_feed, format="rgb", use_video_port=True): 21 | frame = feed.array 22 | 23 | #median blurring frame 24 | #frame = cv2.medianBlur(frame, 3) 25 | 26 | #ycbcr thresholding 27 | framey = cv2.cvtColor(frame, cv2.COLOR_RGB2YCR_CB) #rgb to ycrcb conversion 28 | lower_y = np.array([230,120,60]) 29 | upper_y = np.array([300,300,300]) 30 | thres_mask_y1 = cv2.inRange(framey, lower_y, upper_y) #obtaining binary 31 | #bit_mask_y1 = cv2.bitwise_and(framey, framey, mask= thres_mask_y1) 32 | lower_y2 = np.array([130,180,30]) 33 | upper_y2 = np.array([230,200,90]) 34 | thres_mask_y2 = cv2.inRange(framey, lower_y2, upper_y2) #obtaining binary 35 | #bit_mask_y2 = cv2.bitwise_and(framey, framey, mask= thres_mask_y2) 36 | thres_mask_y = cv2.bitwise_or(thres_mask_y1, thres_mask_y2) #combined mask 37 | 38 | #rgb thresholding 39 | lower_red1 = np.array([230,150,40]) 40 | upper_red1 = np.array([300,300,270]) 41 | thres_mask_red1 = cv2.inRange(frame, lower_red1, upper_red1) 42 | #bit_mask_rgb1 = cv2.bitwise_and(frame, frame, mask= thres_mask_red) 43 | lower_red2 = np.array([200,90,40]) 44 | upper_red2 = np.array([240,120,80]) 45 | thres_mask_red2 = cv2.inRange(frame, lower_red2, upper_red2) 46 | #bit_mask_rgb2 = cv2.bitwise_and(frame, frame, mask= thres_mask_red) 47 | thres_mask_red = cv2.bitwise_or(thres_mask_red1, thres_mask_red2) 48 | 49 | #hsv thresholding 50 | hsv_edit = cv2.cvtColor(frame, cv2.COLOR_RGB2HSV).astype(np.uint8) 51 | lower_blue = np.array([4,100,255]) 52 | upper_blue = np.array([70,300,300]) 53 | thres_mask_hsv = cv2.inRange(hsv_edit, lower_blue, upper_blue) 54 | #bit_mask_hsv = cv2.bitwise_and(frame,frame, mask= thres_mask) 55 | 56 | 57 | #using masks 58 | thres_mask_hsvnrgb = cv2.bitwise_or(thres_mask_hsv, thres_mask_red) 59 | bit_mask_three = cv2.bitwise_and(thres_mask_hsvnrgb, thres_mask_y) 60 | 61 | 62 | #decision making regarding detection 63 | n = cv2.countNonZero(bit_mask_three) 64 | c = 0 65 | if float(n)/float(frame.size) > 0.0005: #need to change 66 | cv2.imshow('Flame Detected', bit_mask_three) 67 | key = cv2.waitKey(1) & 0xFF 68 | 69 | else: 70 | cv2.imshow('Not Detected', frame) 71 | key = cv2.waitKey(1) & 0xFF 72 | 73 | 74 | rawCapture.truncate(0) #clear buffer for next frame !IMPORTANT! 75 | 76 | # if the `q` key was pressed, break from the loop 77 | if key == ord("q"): 78 | break 79 | 80 | cv2.destroyAllWindows() 81 | 82 | 83 | --------------------------------------------------------------------------------