#!/usr/bin/env python 
# coding=utf-8
#1.编译器声明和2.编码格式声明
#1:为了防止用户没有将python安装在默认的/usr/bin目录，系统会先从env(系统环境变量)里查找python的安装路径，再调用对应路径下的解析器完成操作，也可以指定python3
#2:Python.X 源码文件默认使用utf-8编码，可以正常解析中文，一般而言，都会声明为utf-8编码

import cv2 #引用OpenCV功能包
import numpy as np #引用数组功能包

#输入直方图数据，并输出新的直方图数据。新直方图数据按照像素点个数重新排序，数组元素为二元数组[灰度值，像素点个数]
def ResortHist(hist):
    Hist=[]
    i=0
    for pixle in hist:
        a=[i, int(pixle[0])]
        i=i+1
        Hist.append(a)
    Hist.sort(key = lambda x : (x[1]))#按照第二个元素进行升序排序
    return Hist

#输入2元直方图数据、百分比，输出占比前百分比的灰度值平均值
def getTopPercentGrayscale(Hist, Percent):
    #求B通道占比前99%的像素点的灰度值平均值
    percent=0
    i=len(Hist)-1
    while percent<Percent/100 and i>=0:
        percent=percent+Hist[i][1]/totalPixels
        i=i-1
    grayscale_Top_Total=0
    for a in range(i,256):
        grayscale_Top_Total=grayscale_Top_Total+Hist[a][0]
    grayscale_Top=grayscale_Top_Total/(256-i)
    return grayscale_Top

    
#读取视频并获取视频帧率、分辨率
cameraCapture = cv2.VideoCapture(0)
fps=int(cameraCapture.get(cv2.CAP_PROP_FPS))
size_origin = (int(cameraCapture.get(cv2.CAP_PROP_FRAME_WIDTH)),
               int(cameraCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)),)

succes, frame_origin = cameraCapture.read() #读取视频第一帧图片

#从摄像头图片截取区域，将读取该区域的阈值，该区域称为感兴趣区域
interresed_area=[150, 150] #感兴趣区域大小
if succes:
 frame = frame_origin[int(size_origin[1]/2-interresed_area[1]/2):int(size_origin[1]/2+interresed_area[1]/2),
                     int(size_origin[0]/2-interresed_area[0]/2):int(size_origin[0]/2+interresed_area[1]/2)]
totalPixels=interresed_area[0]*interresed_area[1] #感兴趣区域像素点数量总数


#提示停止方法
print ('Showing camera. Press key "Q" to quit.')
Quit=0 #是否继续运行标志位
count=1 #计时全局变量
HistCount=0 #记录读取阈值次数
B_grayscale_Top_sum=0 #用于存放累计灰度值
G_grayscale_Top_sum=0 #用于存放累计灰度值
R_grayscale_Top_sum=0 #用于存放累计灰度值
BGR_Min=[] #用于存放读取阈值结果
BGR_Max=[] #用于存放读取阈值结果
while succes and not Quit:
    keycode=cv2.waitKey(1)
    if(keycode==ord('Q')): #如果按下“Q”键，停止运行标志位置1，跳出while循环，程序停止运行
       Quit=1

    #等待3秒后开始读取阈值，读取10秒(根据摄像头帧率30计算时间)
    if(count>90 and count<390):
        #获得感兴趣区域直方图数据
        hist_B = cv2.calcHist([frame], [0], None, [256], [0,256])
        hist_G = cv2.calcHist([frame], [1], None, [256], [0,256])
        hist_R = cv2.calcHist([frame], [2], None, [256], [0,256])
        
        #创建新的BGR直方图数组，数组元素为二元数组[灰度值，像素点个数]
        Hist_B=ResortHist(hist_B)
        Hist_G=ResortHist(hist_G)
        Hist_R=ResortHist(hist_R)
        
        #求BGR通道占比前45%的像素点的灰度值平均值
        B_grayscale_Top_temp=getTopPercentGrayscale(Hist_B,45)
        G_grayscale_Top_temp=getTopPercentGrayscale(Hist_G,45)
        R_grayscale_Top_temp=getTopPercentGrayscale(Hist_R,45)

        #累计
        B_grayscale_Top_sum=B_grayscale_Top_sum+B_grayscale_Top_temp
        G_grayscale_Top_sum=G_grayscale_Top_sum+G_grayscale_Top_temp
        R_grayscale_Top_sum=R_grayscale_Top_sum+R_grayscale_Top_temp
        HistCount=HistCount+1

        #循环显示与截取感兴趣区域
        cv2.imshow("frame", frame)
        frame = frame_origin[int(size_origin[1]/2-interresed_area[1]/2):int(size_origin[1]/2+interresed_area[1]/2),
                             int(size_origin[0]/2-interresed_area[0]/2):int(size_origin[0]/2+interresed_area[0]/2)]
        print("calculating.")


    #读取完毕，计算阈值
    if(count==390):
        cv2.destroyWindow("frame") #关闭感兴趣区域显示窗口
        B_grayscale_Top=B_grayscale_Top_sum/HistCount
        G_grayscale_Top=G_grayscale_Top_sum/HistCount
        R_grayscale_Top=R_grayscale_Top_sum/HistCount
        ThresholdTolerance=50
        BGR_Min=[int(B_grayscale_Top-ThresholdTolerance),
                 int(G_grayscale_Top-ThresholdTolerance),
                 int(R_grayscale_Top-ThresholdTolerance)]
        BGR_Max=[int(B_grayscale_Top+ThresholdTolerance),
                 int(G_grayscale_Top+ThresholdTolerance),
                 int(R_grayscale_Top+ThresholdTolerance)]

    #计算完毕，打印阈值,并显示该阈值的二值化效果
    if(count>390):    
        print("BGR_MAX:"+str(BGR_Max))
        print("BGR_MIN:"+str(BGR_Min))
        print("\n\t")
        frame_binary = cv2.inRange(frame_origin,np.array(BGR_Min),np.array(BGR_Max))
        cv2.imshow("frame_binary", frame_binary)
   
    #在摄像头原图显示感兴趣区域并显示计时
    cv2.rectangle(frame_origin, (int(size_origin[0]/2-interresed_area[0]/2-5), int(size_origin[1]/2-interresed_area[1]/2)-5),
                                (int(size_origin[0]/2+interresed_area[0]/2+5), int(size_origin[1]/2+interresed_area[1]/2)+5), (255, 0, 0), 3)
    timeShow=int(13-count/30)
    if timeShow<0:timeShow=0
    cv2.putText(frame_origin, str(timeShow), (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)

    #循环显示与读取摄像头
    cv2.imshow("frame_origin", frame_origin)   
    succes, frame_origin = cameraCapture.read() #读取视频第一帧
    count=count+1
    
if succes==0: #提示由于摄像头读取失败停止程序
    print ('Camera disconnect !')
print ('Quitted!') #提示程序已停止
cameraCapture.release() #释放摄像头
cv2.destroyAllWindows() #程序停止前关闭所有窗口
