图像识别|火焰识别系统(python实现基于颜色多帧差分)

实现如下:
通过OpenCV基于火焰颜色特征,通过二帧三针差分减少误差,实现火焰定位识别,然后通过ffmpeg实现推流,流媒体服务器为基于nginx的rtmp流插件实现,请百度nginx-rtmp。
具体实现如下:

# ffmpeg推流命令 def put_to_rtmp(rtmpUrl, sizeStr, fps_num): command = ['ffmpeg', '-y', '-f', 'rawvideo', '-vcodec','rawvideo', '-pix_fmt', 'bgr24', '-s', sizeStr, '-r', str(fps_num), '-i', '-', '-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-preset', 'ultrafast', '-f', 'flv', rtmpUrl] proc = sp.Popen(command, stdin=sp.PIPE, shell=True) #shell= return proc#亮度对比 def contrast_brightness(image, c, b):#其中c为对比度,b为每个像素加上的值(调节亮度) blank = np.zeros(image.shape, image.dtype)#创建一张与原图像大小及通道数都相同的黑色图像 dst = cv2.addWeighted(image, c, blank, 1-c, b) #c为加权值,b为每个像素所加的像素值 ret, dst = cv2.threshold(dst, 127, 255, cv2.THRESH_BINARY) return dst #制图可视化 def drawfire_bak(image,fireimage): display_str = str('火焰预警') image_np = Image.fromarray(image) draw = ImageDraw.Draw(image_np) contours, hierarchy = cv2.findContours(fireimage,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) v_box = [] for i in range(len(contours)): cnt = contours[i] area = cv2.contourArea(cnt) if len(contours) < 4: break x,y,w,h = cv2.boundingRect(cnt) if area>1: v_box.append([x,y]) v_box.append([x+w, y+h])if (len(v_box)>0): v_box = np.array(v_box) minvx,minvy = np.amin(v_box,axis=0) maxvx, maxvy = np.amax(v_box,axis=0)if (len(v_box)>0 ): font = ImageFont.truetype('simhei.ttf', 20,encoding='utf-8') display_str_height = font.getsize(display_str)[1] display_str_heights = (1 + 2 * 0.05) * display_str_height if minvy > display_str_heights: text_bottom = minvy else: text_bottom = maxvy text_width, text_height = font.getsize(display_str) margin = np.ceil(0.05 * text_height) draw.rectangle( [(minvx, text_bottom - text_height - 2 * margin), (minvx + text_width,text_bottom)],fill='blue') draw.text( (minvx + margin, text_bottom - text_height - margin), display_str,fill='yellow',font=font) image = np.array(image_np) cv2.rectangle(image, (minvx,minvy), (maxvx, maxvy), (0, 255, 0), 1) return image#实现火焰识别 rtmpUrl识别结果推流输出地址,url原始输入流地址 def fire_model(url, rtmpUrl): cap = cv2.VideoCapture(url) width =int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height =int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) redThre = 135 saturationTh = 55 ctrl = 3#fourcc = cv2.VideoWriter_fourcc(*'XVID') size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))) sizeStr = str(size[0]) + 'x' + str(size[1]) fps = cap.get(cv2.CAP_PROP_FPS) if fps == 0: raise NameError elif fps < 100: fps_num = int(fps) else: fps_num = int(fps/10000) proc = put_to_rtmp(rtmpUrl, sizeStr ,fps_num)## 二帧差分 if(ctrl==2): frameNum = 0 while(True): ret, frame = cap.read() frameNum += 1 if ret == True: tempframe = frame if(frameNum==1): previousframe = cv2.cvtColor(tempframe, cv2.COLOR_BGR2GRAY) if(frameNum>=2): currentframe = cv2.cvtColor(tempframe, cv2.COLOR_BGR2GRAY) currentframe = cv2.absdiff(currentframe,previousframe) #median = cv2.medianBlur(currentframe,3) ret, threshold_frame = cv2.threshold(currentframe, 20, 255, cv2.THRESH_BINARY) mask_inv = cv2.bitwise_not(threshold_frame) gauss_image = cv2.GaussianBlur(threshold_frame, (3, 3), 0)B = frame[:, :, 0] G = frame[:, :, 1] R = frame[:, :, 2] minValue = https://www.it610.com/article/np.array(np.where(R <= G, np.where(G < B, R, np.where(R < B, R, B)), np.where(G < B, G, B))) S = 1 - 3.0 * minValue / (R + G + B + 1) #fireImg = np.array(np.where(R> redThre, #np.where(R > G, #np.where(G > B, #np.where(S > 0.2, #np.where(S > (255 - R)*saturationTh/redThre, 255, 0), 0), 0), 0), 0)) fireImg = np.array(np.where(R > redThre, np.where(R > G, np.where(G > B, np.where(S > (255 - R)*saturationTh/redThre, 255, 0), 0), 0), 0))gray_fireImg = np.zeros([fireImg.shape[0], fireImg.shape[1], 1], np.uint8) gray_fireImg[:, :, 0] = fireImg gray_fireImg = cv2.GaussianBlur(gray_fireImg, (3, 3), 0)kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) gauss_image = cv2.morphologyEx(gauss_image, cv2.MORPH_OPEN, kernel) cv2.imshow("gauss_image",gauss_image)gray_fireImg = contrast_brightness(gray_fireImg, 5., 25) cv2.imshow("gray_fireImg",gray_fireImg) gray_fireImg = cv2.bitwise_and(gray_fireImg,gauss_image,mask=mask_inv)image = drawfire_bak(frame, gray_fireImg) cv2.imshow("img", image) if cv2.waitKey(1) & 0xFF == ord('q'): break #rtmp流写入 try: proc.stdin.write(image.tobytes()) except Exception as e: proc.stdin.close() proc = put_to_rtmp(rtmpUrl, sizeStr ,fps_num) previousframe = cv2.cvtColor(tempframe, cv2.COLOR_BGR2GRAY) else: break proc.stdin.close() cap.release() cv2.destroyAllWindows() ## 三帧差分法 else: one_frame = np.zeros((height,width),dtype=np.uint8) two_frame = np.zeros((height,width),dtype=np.uint8) three_frame = np.zeros((height,width),dtype=np.uint8) while(True): ret, frame = cap.read() if ret == True: frame_gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) one_frame,two_frame,three_frame = two_frame,three_frame,frame_gray abs1 = cv2.absdiff(one_frame,two_frame)#相减 _,thresh1 = cv2.threshold(abs1,20,255,cv2.THRESH_BINARY)#二值,大于20的为255,小于0 abs2 =cv2.absdiff(two_frame,three_frame) _,thresh2 =cv2.threshold(abs2,20,255,cv2.THRESH_BINARY)binary =cv2.bitwise_and(thresh1,thresh2)B = frame[:, :, 0] G = frame[:, :, 1] R = frame[:, :, 2] minValue = https://www.it610.com/article/np.array(np.where(R <= G, np.where(G < B, R, np.where(R < B, R, B)), np.where(G < B, G, B))) RGB_sum = R + G + B RGB_sum[RGB_sum == 0] = 1 S = 1 - 3.0 * minValue / RGB_sum #fireImg = np.array(np.where(R> redThre, #np.where(R > G, #np.where(G > B, #np.where(S > 0.2, #np.where(S > (255 - R)*saturationTh/redThre, 255, 0), 0), 0), 0), 0)) estimate = (255 - R)*saturationTh/redThre fireImg = np.array(np.where(R > redThre, np.where(R > G, np.where(G > B, np.where(S > estimate, 255, 0), 0), 0), 0))gray_fireImg = np.zeros([fireImg.shape[0], fireImg.shape[1], 1], np.uint8) gray_fireImg[:, :, 0] = fireImg gray_fireImg = cv2.GaussianBlur(gray_fireImg, (3, 3), 0)#kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) #binary = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel)gray_fireImg = contrast_brightness(gray_fireImg, 5., 25) gray_fireImg = cv2.bitwise_and(gray_fireImg,binary)image = drawfire_bak(frame, gray_fireImg) #cv2.imshow("img", image) #if cv2.waitKey(1) & 0xFF == ord('q'): #break #rtmp流写入 try: proc.stdin.write(image.tobytes()) except Exception as e: proc.stdin.close() proc = put_to_rtmp(rtmpUrl, sizeStr ,fps_num) else: break proc.stdin.close() cap.release() cv2.destroyAllWindows()

参考文章:识别检测类系统(基于pytorch)(一)_明哲慕鸿的博客-CSDN博客_基于pytorch的物体识别
【图像识别|火焰识别系统(python实现基于颜色多帧差分)】识别检测类系统(基于pytorch)(一) - 灰信网(软件开发博客聚合)

    推荐阅读