import cv2
import numpy
import os
import RPi.GPIO as GPIO
import time
import serial

from imutils import perspective

TRACKING_WIDTH = 51
BLACK_BAR_WIDTH = 8
WIDE_TRACKING_WIDTH = TRACKING_WIDTH + BLACK_BAR_WIDTH * 2
TRACKING_HEIGHT = 231

TURBO_PIN = 5
POWER_ON_PIN = 6
PAUSE_BUTTON_PIN = 13
TRIGGER_BUTTON_PIN = 19
CURSOR_BUTTON_PIN = 26

BT_MESSAGE_TRIGGER_PRESSED = 231
BT_MESSAGE_TRIGGER_RELEASED = 232
BT_MESSAGE_CURSOR_PRESSED = 233
BT_MESSAGE_CURSOR_RELEASED = 234
BT_MESSAGE_TURBO_ENABLED = 235
BT_MESSAGE_TURBO_DISABLED = 236
BT_MESSAGE_PAUSE_PRESSED = 237
BT_MESSAGE_PAUSE_RELEASED = 238
BT_MESSAGE_TV_NOT_VISIBLE = 239
BT_MESSAGE_AIM_X = 240
BT_MESSAGE_AIM_Y = 241

isTvVisible = False

GPIO.setmode(GPIO.BCM)

GPIO.setup(TURBO_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(POWER_ON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(PAUSE_BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(TRIGGER_BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(CURSOR_BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

serialPort = serial.Serial(port = "/dev/rfcomm0")

def handleButtons(channel):
    isRising = GPIO.input(channel)

    if channel == TURBO_PIN:
        serialPort.write(bytearray([BT_MESSAGE_TURBO_ENABLED]) if isRising else bytearray([BT_MESSAGE_TURBO_DISABLED]))
    elif channel == POWER_ON_PIN:
        if not isRising:
            os.system("shutdown now -h")
    elif channel == PAUSE_BUTTON_PIN:
        serialPort.write(bytearray([BT_MESSAGE_PAUSE_PRESSED]) if isRising else bytearray([BT_MESSAGE_PAUSE_RELEASED]))
    elif channel == TRIGGER_BUTTON_PIN:
        serialPort.write(bytearray([BT_MESSAGE_TRIGGER_PRESSED]) if isRising else bytearray([BT_MESSAGE_TRIGGER_RELEASED]))
    elif channel == CURSOR_BUTTON_PIN:
        serialPort.write(bytearray([BT_MESSAGE_CURSOR_PRESSED]) if isRising else bytearray([BT_MESSAGE_CURSOR_RELEASED]))

handleButtons(TURBO_PIN)

GPIO.add_event_detect(TURBO_PIN, GPIO.BOTH, callback = handleButtons, bouncetime = 10)
GPIO.add_event_detect(POWER_ON_PIN, GPIO.BOTH, callback = handleButtons, bouncetime = 10)
GPIO.add_event_detect(PAUSE_BUTTON_PIN, GPIO.BOTH, callback = handleButtons, bouncetime = 10)
GPIO.add_event_detect(TRIGGER_BUTTON_PIN, GPIO.BOTH, callback = handleButtons, bouncetime = 10)
GPIO.add_event_detect(CURSOR_BUTTON_PIN, GPIO.BOTH, callback = handleButtons, bouncetime = 10)

camera = cv2.VideoCapture(0)

if camera.isOpened():
    camera.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
    camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)

windowName = "Super Scope"
cv2.namedWindow(windowName)

while True:
    wasFrameGrabSuccessful, frame = camera.read()

    if wasFrameGrabSuccessful:
        grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        _, threshold = cv2.threshold(grayFrame, 127, 255, cv2.THRESH_BINARY)
        contours, _ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

        finalFrame = cv2.cvtColor(grayFrame, cv2.COLOR_GRAY2BGR)

        trackingPointCount = 0
        trackingPoints = numpy.zeros(shape = (4, 2), dtype = numpy.float32)

        for contour in contours:
            moments = cv2.moments(contour)

            if moments["m00"] > 10:
                if trackingPointCount < 5:
                    centerX = int(moments["m10"] / moments["m00"])
                    centerY = int(moments["m01"] / moments["m00"])
                    trackingPoints[trackingPointCount] = [centerX, centerY]
                    cv2.circle(finalFrame, (centerX, centerY), 5, (0, 255, 0), cv2.FILLED)

                trackingPointCount += 1

        trackingPoints = perspective.order_points(trackingPoints)

        # Draw red dot at center.
        cv2.circle(finalFrame, (320, 240), 5, (0, 0, 255), cv2.FILLED)

        # Outline transformed area in blue.
        cv2.rectangle(finalFrame, (0, 0), (TRACKING_WIDTH, TRACKING_HEIGHT), (255, 0, 0), 3)

        if trackingPointCount == 4:
            destPoints = numpy.array([[0, 0], [WIDE_TRACKING_WIDTH - 1, 0], [WIDE_TRACKING_WIDTH - 1, TRACKING_HEIGHT - 1], [0, TRACKING_HEIGHT - 1]], dtype = numpy.float32)
            transform = cv2.getPerspectiveTransform(trackingPoints[:, numpy.newaxis, :], destPoints[:, numpy.newaxis, :])
            transformed = cv2.perspectiveTransform(numpy.array([[320, 240]], dtype = numpy.float32)[:, numpy.newaxis, :], transform)

            transformedX = int(transformed[0][0][0] - BLACK_BAR_WIDTH)
            transformedY = int(transformed[0][0][1])

            # Draw transformed tracking point in yellow.
            cv2.circle(finalFrame, (transformedX, transformedY), 5, (0, 255, 255), cv2.FILLED)

            if (0 <= transformedX < TRACKING_WIDTH) and (0 <= transformedY < TRACKING_HEIGHT):
                isTvVisible = True;
                serialPort.write(bytearray([BT_MESSAGE_AIM_X, transformedX, BT_MESSAGE_AIM_Y, transformedY]))
            elif isTvVisible:
                isTvVisible = False;
                serialPort.write(bytearray([BT_MESSAGE_TV_NOT_VISIBLE]))
        elif isTvVisible:
            isTvVisible = False;
            serialPort.write(bytearray([BT_MESSAGE_TV_NOT_VISIBLE]))

        cv2.imshow(windowName, finalFrame)

    if cv2.waitKey(1) % 0xFF == 27:  # Escape key
        break

camera.release()
cv2.destroyAllWindows()
GPIO.cleanup()


import os
import cv2
import pickle
import numpy as np
from keras.models import load_model

path = 'test_data' # test data set folder path
model = load_model('models/COVID-19-model.h5')
labels = pickle.load(open('models/labels.pkl','rb'))
labelsValues = ['Covid - 19', 'Normal']
font = cv2.FONT_HERSHEY_COMPLEX_SMALL

def getPrediction():
    predictionValue = ''
    imagePaths = [os.path.join(path, f) for f in os.listdir(path)]
    for imagePath in imagePaths:
        image = cv2.imread(imagePath)
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        image = cv2.resize(image, (224, 224))
        image = np.array(image) / 255.0
        image = image.reshape(224, 224, -1)
        image1 = np.expand_dims(image, axis=0)
        prediction = model.predict(image1)
        prediction = np.argmax(prediction, axis=1)
        predictionValue = np.int(labels[prediction[0].astype('int64')][0])
        if predictionValue == 0:
            cv2.putText(image, labelsValues[predictionValue], (50,40), font, 1,(255,0,0), 1, cv2.LINE_AA)
        else:
            cv2.putText(image, labelsValues[predictionValue], (50, 40), font, 1, (255, 255, 255), 1, cv2.LINE_AA)
        cv2.imshow('COVID-19: window', image)
        cv2.waitKey(500)
        if cv2.waitKey(25) & 0xFF == ord('q'):
            cv2.destroyAllWindows()
            break

if __name__ == '__main__':
    getPrediction()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""ICU Prediction API: Simulator.

Author: Bas Vonk
Date: 2019-04-01
"""

from random import random, choice, randrange
from datetime import datetime, timedelta
from time import sleep
import logging
from numpy.random import normal
from faker import Faker
import coloredlogs
from src.mysql_adapter import MySQL

SECONDS_IN_MINUTE = 60
MINUTES_IN_DAY = 1440

DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"

FLIP_A_COIN = 0.5

# SIMULATION PARAMETERS:
PATIENTS_ADMITTED_PER_DAY = 2
PATIENTS_DISCHARGED_PER_DAY = 2
MEASUREMENTS_PER_DAY_PER_SIGNAL = 144

FREQ_ADMISSION = PATIENTS_ADMITTED_PER_DAY / MINUTES_IN_DAY
FREQ_DISCHARGE = PATIENTS_DISCHARGED_PER_DAY / MINUTES_IN_DAY
FREQ_MEASUREMENTS = MEASUREMENTS_PER_DAY_PER_SIGNAL / MINUTES_IN_DAY

DATETIME_START = "2019-01-01 00:00:00"

# A day takes 1440 (24 * 60) iterations/minutes. For a fake day to last 5 minutes, we need to sleep
# 1 / 24 seconds for each iteration/minute
SLOW_FACTOR = 1 / 24

AVAILABLE_BEDS = ['BED_01', 'BED_02', 'BED_03', 'BED_04', 'BED_05', 'BED_06', 'BED_07', 'BED_08',
                  'BED_09', 'BED_10', 'BED_11', 'BED_12', 'BED_13', 'BED_14', 'BED_15', 'BED_16',
                  'BED_17', 'BED_18', 'BED_19', 'BED_20', 'BED_21', 'BED_22', 'BED_23', 'BED_24']
IC_AVERAGE_PATIENT_AMOUNT = int(len(AVAILABLE_BEDS) / 2)

# Define a logger
LOGGER = logging.getLogger('Simulator')
coloredlogs.install(logger=LOGGER)

class Simulator:
    """Class to simulate daily life at the Intensive Care.

    Attributes
    ----------
    mysql_obj : MySQL
        An instance of the MySQL class
    faker_obj : Faker
        An instance of the Faker class.
    current_datetime : datetime
        The current datetime (in the simulation, not the actual datetime)
    available_beds : List[str]
        Object that lists all available beds
    patients_in_ic : List[Dict[str, Union[str, datetime, int]]]
        List with patients that are currently in the IC
    signals : List[Dict[str, Union[str, datetime, int]]]
        List with all signals that are available for this simulation

    """

    def __init__(self):

        # Create necessary connections and objects
        self.mysql_obj: MySQL = MySQL()
        self.faker_obj = Faker('nl_NL')
        self.current_datetime = datetime.strptime(DATETIME_START, DATETIME_FORMAT)
        self.available_beds = AVAILABLE_BEDS
        self.patients_in_ic = []
        self.signals = self.get_signals()

    def get_signals(self):
        """Get all the signals from the database."""

        return self.mysql_obj.fetch_rows("SELECT * FROM signals")

    def reset_simulation(self):
        """Reset the simulation."""

        # Clean the database from previous simulations
        self.mysql_obj.execute_query("TRUNCATE patients")
        self.mysql_obj.execute_query("TRUNCATE patient_signal_values")

    def possibly_admit_patient(self, always_admit=False):
        """Admit a fake patient."""

        # General strategy:
        # 1. Decide whether to admit a fake patient, based on chance and whether there are free beds
        # 2. Assign a bed (and remove it from the 'free beds' list)
        # 3. Build a fake patient object
        # 4. Add the fake patient to the database and to the patients_in_ic object

        if (self.decision(FREQ_ADMISSION) and self.available_beds) or always_admit:

            # Get a bed from the available bed list while at the same time removing it from that
            # list (a bed can only be assigned once)
            bed = self.available_beds.pop(randrange(len(self.available_beds)))

            # Simulate a date of birthe for this patient
            date_of_birth = self.faker_obj.date_of_birth()

            # Construct a fake patient
            patient = {
                "first_name": self.faker_obj.first_name(),
                "last_name": self.faker_obj.last_name(),
                "date_of_birth": date_of_birth,
                "age": (self.current_datetime.date() - date_of_birth).days / 365,
                "datetime_admission": self.current_datetime,
                "bed": bed
            }

            patient['id'] = self.mysql_obj.replace_into(table_name='patients', values=patient)
            self.patients_in_ic.append(patient)
            LOGGER.info(f"Patient admitted to the IC in bed: {bed}.")

    def possibly_discharge_patient(self):
        """Discharge a random patient."""

        # General strategy:
        # 1. Decide whether to admit a fake patient, based on chance:
        #    This is built in a way that the chance of discharge is actually influenced by
        #    the average amount of patients that can be in the IC. On average we discharge 2
        #    patients per day (same as the amount of patients admitted), but we increase the
        #    chance of discharge when there's many patients in the IC and decrease the change when
        #    there's little patients in the IC. The purpose is to always keep around 12 patients
        #    at the IC.
        # 2. Pick a random patient currently at the IC
        # 3. Set the discharge time (this is the 'current' time)
        # 4. Update the patient in the database
        # 5. Remove the patient from the list with patients currently in the IC
        # 6. Make the bed the patient was in available again
        #
        if self.decision(FREQ_DISCHARGE * len(self.patients_in_ic) / IC_AVERAGE_PATIENT_AMOUNT):

            # Sometimes pick the patient longest in the IC, sometimes pick a random patient
            # (This is done to ensure people don't remain in the IC forever)
            patient = choice(self.patients_in_ic)

            # Discharge the patient in the database
            patient['datetime_discharge'] = self.current_datetime

            # Update the patient and
            # 1. Remove the patient from the IC
            # 2. Return the bed to the available beds
            self.mysql_obj.replace_into(table_name='patients', values=patient)
            self.patients_in_ic.remove(patient)
            self.available_beds.append(patient['bed'])
            LOGGER.info("Patient discharged from the IC.")

    def simulate_values_for_patients_in_ic(self):
        """Simulate values for patients that are currently in the IC."""

        # General strategy:
        # 1. Loop over all patients
        #    1.1 Loop over all signals that are in the simulation
        #        1.1.1 For each signal build the row-object
        #              The value is drawn from a normal distribution with population meand and std
        #        1.1.2 Replace the row into the database

        for patient in self.patients_in_ic:

            for signal in self.signals:

                if self.decision(FREQ_MEASUREMENTS):

                    row = {
                        'patient_id': patient['id'],
                        'signal_id': signal['id'],
                        'time': self.current_datetime,
                        'value': normal(signal['population_mean'], signal['population_std'])
                    }

                    LOGGER.info(f"{signal['name']} with value {row['value']} registered for {patient['first_name']}.")
                    self.mysql_obj.replace_into(table_name='patient_signal_values', values=row)

    def next_minute(self):
        """Increase the current datetime with one minute."""

        self.current_datetime = self.current_datetime + timedelta(seconds=SECONDS_IN_MINUTE)
        LOGGER.info(f"Current time: {self.current_datetime}")

    @staticmethod
    def decision(probability: float):
        """Get a True with certain probability, or a False otherwise.

        Parameters
        ----------
        probability : float
            The probability with which to return a True.

        Returns
        -------
        bool
            A decision on True or False

        """
        return random() < probability

def run_simulation():
    """Run the simulation."""

    # General strategy:
    # 1. Initialize the Simulator class
    # 2. Reset the simulation (remove all patients and values)
    # 3. Initially admit a certain amount of patients
    # 4. Start simulating minutes, for each minute:
    #    4.1 Possibly discharge a patient (on average 2 per day)
    #    4.2 Simulate values for the patients that are still in the IC
    #    4.3 Possibly admit a patient (on average 2 per day)
    #    4.4 Go to the next minute
    #    4.5 Sleep a while to control the speed of the simulation

    simulator_obj = Simulator()

    simulator_obj.reset_simulation()

    # Admit initial patients
    for _ in range(IC_AVERAGE_PATIENT_AMOUNT):
        simulator_obj.possibly_admit_patient(always_admit=True)

    while True:

        simulator_obj.possibly_discharge_patient()

        simulator_obj.simulate_values_for_patients_in_ic()

        simulator_obj.possibly_admit_patient()

        simulator_obj.next_minute()

        sleep(SLOW_FACTOR)

if __name__ == '__main__':

    run_simulation()


"""Radar module, containing the :class:`Radar` class."""
import math
from typing import Union
import numpy as np
import numpy.ma as ma
from scipy import constants
from cloudnetpy.categorize import DataSource
from cloudnetpy.categorize.classify import ClassificationResult
from cloudnetpy import utils
import logging

class Radar(DataSource):
    """Radar class, child of DataSource.

    Args:
        full_path: Cloudnet Level 1 radar netCDF file.

    Attributes:
        radar_frequency (float): Radar frequency (GHz).
        folding_velocity (float): Radar's folding velocity (m/s).
        location (str): Location of the radar, copied from the global attribute `location` of the
            input file.
        sequence_indices (list): Indices denoting the different altitude
            regimes of the radar.
        type (str): Type of the radar, copied from the global attribute
            `source` of the *radar_file*. Can be free form string but must
            include either 'rpg' or 'mira' denoting one of the two supported
            radars.

    See Also:
        :func:`instruments.rpg2nc()`, :func:`instruments.mira2nc()`

    """
    def __init__(self, full_path: str):
        super().__init__(full_path, radar=True)
        self.radar_frequency = float(self.getvar('radar_frequency', 'frequency'))
        self.folding_velocity = self._get_folding_velocity()
        self.sequence_indices = self._get_sequence_indices()
        self.location = getattr(self.dataset, 'location', '')
        self.type = getattr(self.dataset, 'source', '')
        self._init_data()
        self._init_sigma_v()

    def rebin_to_grid(self, time_new: np.ndarray) -> None:
        """Rebins radar data in time using mean.

        Args:
            time_new: Target time array as fraction hour. Updates *time* attribute.

        """
        for key in self.data:
            if key in ('Z', 'ldr'):
                self.data[key].db2lin()
                self.data[key].rebin_data(self.time, time_new)
                self.data[key].lin2db()
            elif key == 'v':
                self.data[key].rebin_velocity(self.time, time_new,
                                              self.folding_velocity,
                                              self.sequence_indices)
            elif key == 'v_sigma':
                self.data[key].calc_linear_std(self.time, time_new)
            else:
                self.data[key].rebin_data(self.time, time_new)
        self.time = time_new

    def remove_incomplete_pixels(self) -> None:
        """Mask radar pixels where one or more required quantities are missing.

        All valid radar pixels **must** contain proper values for `Z`, and `v` and
        also for `width` if exists. Otherwise there is some kind of problem with the
        data and the pixel should not be used in any further analysis.

        """
        good_ind = (~ma.getmaskarray(self.data['Z'][:])
                    & ~ma.getmaskarray(self.data['v'][:]))

        if 'width' in self.data.keys():
            good_ind = good_ind & ~ma.getmaskarray(self.data['width'][:])

        for array in self.data.values():
            array.mask_indices(~good_ind)

    def filter_speckle_noise(self) -> None:
        """Removes speckle noise from radar data.

        Any isolated radar pixel, i.e. "hot pixel", is assumed to
        exist due to speckle noise. This is a crude approach and a
        more sophisticated method could be implemented here later.

        """
        for key in ('Z', 'v', 'width', 'ldr', 'v_sigma'):
            if key in self.data.keys():
                self.data[key].filter_vertical_stripes()

    def filter_1st_gate_artifact(self) -> None:
        """Removes 1st range gate velocity artifact."""
        velocity_limit = 4
        ind = np.where(self.data['v'][:, 0] > velocity_limit)
        self.data['v'][:][ind, 0] = ma.masked

    def filter_stripes(self, variable: str) -> None:
        """Filters vertical and horizontal stripe-shaped artifacts from radar data."""
        if variable not in self.data:
            return
        data = self.data[variable][:]
        n_points_in_profiles = ma.count(data, axis=1)
        n_profiles_with_data = np.count_nonzero(n_points_in_profiles)
        if n_profiles_with_data < 300:
            return
        n_vertical = self._filter(data, 1, min_coverage=0.5, z_limit=10, distance=4, n_blocks=100)
        n_horizontal = self._filter(data, 0, min_coverage=0.3, z_limit=-30, distance=3, n_blocks=20)
        if n_vertical > 0 or n_horizontal > 0:
            logging.info(f'Filtered {n_vertical} vertical and {n_horizontal} horizontal stripes '
                         f'from radar data using {variable}')

    def _filter(self, data: np.array,
                axis: int,
                min_coverage: float,
                z_limit: float,
                distance: float,
                n_blocks: int) -> int:

        if axis == 0:
            data = data.T
            echo = self.data['Z'][:].T
        else:
            echo = self.data['Z'][:]

        len_block = int(np.floor(data.shape[0] / n_blocks))
        block_indices = np.arange(len_block)
        n_removed_total = 0

        for block_number in range(n_blocks):

            data_block = data[block_indices, :]
            n_values = ma.count(data_block, axis=1)

            try:
                q1 = np.quantile(n_values, 0.25)
                q3 = np.quantile(n_values, 0.75)
            except IndexError:
                continue
            threshold = distance * (q3 - q1) + q3

            ind = np.where((n_values > threshold) & (n_values > (min_coverage * data.shape[1])))[0]
            true_ind = [int(x) for x in (block_number * len_block + ind)]
            n_removed = len(ind)

            if n_removed > 5:
                continue

            if n_removed > 0:
                n_removed_total += n_removed
                for ind in true_ind:
                    ind2 = np.where(echo[ind, :] < z_limit)
                    indices = [ind, ind2] if axis == 1 else [ind2, ind]
                    self.data['v'][:][indices] = ma.masked
            block_indices += len_block

        return n_removed_total

    def correct_atten(self, attenuations: dict) -> None:
        """Corrects radar echo for liquid and gas attenuation.

        Args:
            attenuations: 2-D attenuations due to atmospheric gases and liquid: `radar_gas_atten`,
                `radar_liquid_atten`.

        References:
            The method is based on Hogan R. and O'Connor E., 2004, https://bit.ly/2Yjz9DZ
            and the original Cloudnet Matlab implementation.

        """
        z_corrected = self.data['Z'][:] + attenuations['radar_gas_atten']
        ind = ma.where(attenuations['radar_liquid_atten'])
        z_corrected[ind] += attenuations['radar_liquid_atten'][ind]
        self.append_data(z_corrected, 'Z')

    def calc_errors(self, attenuations: dict, classification: ClassificationResult) -> None:
        """Calculates uncertainties of radar echo.

        Calculates and adds `Z_error`, `Z_sensitivity` and `Z_bias` :class:`CloudnetArray`
        instances to `data` attribute.

        Args:
            attenuations: 2-D attenuations due to atmospheric gases.
            classification: The :class:`ClassificationResult` instance.

        References:
            The method is based on Hogan R. and O'Connor E., 2004, https://bit.ly/2Yjz9DZ
            and the original Cloudnet Matlab implementation.

        """
        def _calc_sensitivity() -> np.ndarray:
            """Returns sensitivity of radar as function of altitude."""
            mean_gas_atten = ma.mean(attenuations['radar_gas_atten'], axis=0)
            z_sensitivity = z_power_min + log_range + mean_gas_atten
            zc = ma.median(ma.array(z, mask=~classification.is_clutter), axis=0)
            z_sensitivity[~zc.mask] = zc[~zc.mask]
            return z_sensitivity

        def _calc_error() -> np.ndarray:
            if 'width' not in self.data:
                return 0.3
            z_precision = 4.343 * (1 / np.sqrt(_number_of_independent_pulses())
                                   + utils.db2lin(z_power_min - z_power) / 3)
            gas_error = attenuations['radar_gas_atten'] * 0.1
            liq_error = attenuations['liquid_atten_err'].filled(0)
            z_error = utils.l2norm(gas_error, liq_error, z_precision)
            z_error[attenuations['liquid_uncorrected']] = ma.masked
            return z_error

        def _number_of_independent_pulses() -> float:
            seconds_in_hour = 3600
            dwell_time = utils.mdiff(self.time) * seconds_in_hour
            return (dwell_time * self.radar_frequency * 1e9 * 4
                    * np.sqrt(math.pi) * self.data['width'][:] / 3e8)

        def _calc_z_power_min() -> float:
            if ma.all(z_power.mask):
                return 0
            return np.percentile(z_power.compressed(), 0.1)

        z = self.data['Z'][:]
        radar_range = self.km2m(self.dataset.variables['range'])
        log_range = utils.lin2db(radar_range, scale=20)
        z_power = z - log_range
        z_power_min = _calc_z_power_min()
        self.append_data(_calc_error(), 'Z_error')
        self.append_data(_calc_sensitivity(), 'Z_sensitivity')
        self.append_data(1, 'Z_bias')

    def add_meta(self) -> None:
        """Copies misc. metadata from the input file."""
        for key in ('latitude', 'longitude', 'altitude'):
            self.append_data(np.array(self.getvar(key)), key)
        for key in ('time', 'height', 'radar_frequency'):
            self.append_data(np.array(getattr(self, key)), key)

    def _init_data(self):
        self._unknown_variable_to_cloudnet_array(('Ze',), 'Z', units='dBZ')
        for key in ('v', 'ldr', 'width'):
            try:
                self._variables_to_cloudnet_arrays((key,))
            except KeyError:
                continue

    def _init_sigma_v(self) -> None:
        """Initializes std of the velocity field. The std will be calculated
        later when re-binning the data."""
        self.append_data(self.getvar('v'), 'v_sigma')

    def _get_sequence_indices(self) -> list:
        """Mira has only one sequence and one folding velocity. RPG has
        several sequences with different folding velocities."""
        all_indices = np.arange(len(self.height))
        if not utils.isscalar(self.folding_velocity):
            starting_indices = self.getvar('chirp_start_indices')
            return np.split(all_indices, starting_indices[1:])
        return [all_indices]

    def _get_folding_velocity(self) -> Union[np.ndarray, float]:
        for key in ('nyquist_velocity', 'NyquistVelocity'):
            if key in self.dataset.variables:
                return self.getvar(key)
        if 'prf' in self.dataset.variables:
            prf = self.getvar('prf')
            return _prf_to_folding_velocity(prf, self.radar_frequency)
        raise RuntimeError('Unable to determine folding velocity')

def _prf_to_folding_velocity(prf: np.ndarray, radar_frequency: float) -> float:
    ghz_to_hz = 1e9
    return float(prf * constants.c / (4*radar_frequency*ghz_to_hz))


import numpy as np
from pymodaq.daq_utils.gui_utils.custom_app import CustomApp
from pymodaq.daq_utils.gui_utils.dock import Dock, DockArea
from pymodaq.daq_utils.gui_utils.file_io import select_file
from pymodaq.daq_utils.gui_utils.widgets.table import TableModel, SpinBoxDelegate

from qtpy import QtWidgets, QtCore, QtGui
from qtpy.QtWidgets import QWidget
from pymodaq.daq_utils import daq_utils as utils
from pymodaq.daq_utils import gui_utils as gutils
from pymodaq.daq_utils.scanner import TableModelSequential
from pyqtgraph.parametertree import Parameter, ParameterTree
from pymodaq.daq_utils.parameter import pymodaq_ptypes as ptypes
from pymodaq.daq_utils.parameter import utils as putils
from pymodaq.daq_utils.plotting.data_viewers.viewer1D import Viewer1D
from pymodaq.daq_utils.messenger import dialog

class TableViewCustom(QtWidgets.QTableView):
    """
        ============== ===========================
        *Attributes**    **Type**
        *valuechanged*   instance of pyqt Signal
        *QtWidgets*      instance of QTableWidget
        ============== ===========================
    """

    valueChanged = QtCore.Signal(list)
    add_data_signal = QtCore.Signal(int)
    remove_row_signal = QtCore.Signal(int)

    def __init__(self, menu=False):
        super().__init__()
        self.setmenu(menu)

    def setmenu(self, status):
        if status:
            self.menu = QtWidgets.QMenu()
            self.menu.addAction('Add new', self.add)
            self.menu.addAction('Remove selected row', self.remove)
            self.menu.addAction('Clear all', self.clear)
            self.menu.addSeparator()
        else:
            self.menu = None

    def clear(self):
        self.model().clear()

    def add(self):
        self.add_data_signal.emit(self.currentIndex().row())

    def remove(self):
        self.remove_row_signal.emit(self.currentIndex().row())

    def data_has_changed(self, topleft, bottomright, roles):
        self.valueChanged.emit([topleft, bottomright, roles])

    def get_table_value(self):
        """

        """
        return self.model()

    def set_table_value(self, data_model):
        """

        """
        try:
            self.setModel(data_model)
            self.model().dataChanged.connect(self.data_has_changed)
        except Exception as e:
            pass

    def contextMenuEvent(self, event):
        if self.menu is not None:
            self.menu.exec(event.globalPos())

class TableModelSequential(TableModel):
    def __init__(self, data, **kwargs):
        header = ['Start', 'Stop', 'Step']
        editable = [True, True, True]
        self.default_row = [0., 1., 0.1]
        super().__init__(data, header=header, editable=editable, show_checkbox=True, **kwargs)

    def __repr__(self):
        return f'{self.__class__.__name__} from module {self.__class__.__module__}'

    def validate_data(self, row, col, value):
        """
        make sure the values and signs of the start, stop and step values are "correct"
        Parameters
        ----------
        row: (int) row within the table that is to be changed
        col: (int) col within the table that is to be changed
        value: (float) new value for the value defined by row and col

        Returns
        -------
        bool: True is the new value is fine (change some other values if needed) otherwise False
        """
        start = self.data(self.index(row, 0), QtCore.Qt.DisplayRole)
        stop = self.data(self.index(row, 1), QtCore.Qt.DisplayRole)
        step = self.data(self.index(row, 2), QtCore.Qt.DisplayRole)
        isstep = False
        if col == 0:  # the start
            start = value
        elif col == 1:  # the stop
            stop = value
        elif col == 2:  # the step
            isstep = True
            step = value

        if np.abs(step) < 1e-12 or start == stop:
            return False
        if np.sign(stop - start) != np.sign(step):
            if isstep:
                self._data[row][1] = -stop
            else:
                self._data[row][2] = -step
        return True

    @QtCore.Slot(int)
    def add_data(self, row, data=None):
        if data is not None:
            self.insert_data(row, [float(d) for d in data])
        else:
            self.insert_data(row, self.default_row)

    @QtCore.Slot(int)
    def remove_data(self, row):
        self.remove_row(row)

    def load_txt(self):
        fname = select_file(start_path=None, save=False, ext='*')
        if fname is not None and fname != '':
            while self.rowCount(self.index(-1, -1)) > 0:
                self.remove_row(0)

            data = np.loadtxt(fname)
            if len(data.shape) == 1:
                data = data.reshape((data.size, 1))
            self.set_data_all(data)

    def save_txt(self):
        fname = select_file(start_path=None, save=True, ext='dat')
        if fname is not None and fname != '':
            np.savetxt(fname, self.get_data_all(), delimiter='\t')

class ItemDelegate(QtWidgets.QAbstractItemDelegate):
    def createEditor(self, parent: QWidget, option: 'QStyleOptionViewItem', index: QtCore.QModelIndex) -> QWidget:
        pass

    def setEditorData(self, editor: QWidget, index: QtCore.QModelIndex) -> None:
        pass

    def setModelData(self, editor: QWidget, model: QtCore.QAbstractItemModel, index: QtCore.QModelIndex) -> None:
        pass

class StepsSequencer(CustomApp):

    positions_signal = QtCore.Signal(np.ndarray)
    params = [dict(title='Npts', name='npts', type='int', readonly=True),
              dict(title='', label='Send Points', name='send_points', type='bool_push'),
              dict(title='', label='Show Points', name='show_points', type='bool_push'),
              dict(title='Steps', name='table', type='table_view', delegate=SpinBoxDelegate, menu=True)]

    def __init__(self, dockarea):
        super().__init__(dockarea)

        self._table_model = None
        self._table_view = None

        self.setup_table_view()
        self.update_model()
        self.setup_ui()

    def connect_things(self):
        pass

    def setup_actions(self):
        '''
        subclass method from ActionManager
        '''
        pass

    def setup_docks(self):
        '''
        subclass method from CustomApp
        '''
        self.dock = Dock('Steps Sequencer', size=(350, 350))
        self.dockarea.addDock(self.dock, 'left')
        self.dock.addWidget(self.settings_tree, 10)
        self.settings_tree.setMinimumSize(350, 200)

    def emit_positions(self):
        self.positions_signal.emit(np.transpose(np.array([self.update_steps_calculation()])))

    def setup_table_view(self):
        self._table_view = putils.get_widget_from_tree(self.settings_tree, ptypes.TableViewCustom)[0]
        styledItemDelegate = QtWidgets.QStyledItemDelegate()
        styledItemDelegate.setItemEditorFactory(SpinBoxDelegate(decimals=6))
        self._table_view.setItemDelegate(styledItemDelegate)

        #self._table_view.horizontalHeader().setResizeMode(QtWidgets.QHeaderView.ResizeToContents)
        self._table_view.horizontalHeader().setStretchLastSection(True)
        self._table_view.setSelectionBehavior(QtWidgets.QTableView.SelectRows)
        self._table_view.setSelectionMode(QtWidgets.QTableView.SingleSelection)

        self._table_view.setDragEnabled(True)
        self._table_view.setDropIndicatorShown(True)
        self._table_view.setAcceptDrops(True)
        self._table_view.viewport().setAcceptDrops(True)
        self._table_view.setDefaultDropAction(QtCore.Qt.MoveAction)
        self._table_view.setDragDropMode(QtWidgets.QTableView.InternalMove)
        self._table_view.setDragDropOverwriteMode(False)

    def update_model(self):
        Nseqs = 1
        default_row = [0., 1., 0.1]
        init_data = [default_row for _ in range(Nseqs)]
        self._table_model = TableModelSequential(init_data)
        self.settings.child('table').setValue(self._table_model)

        self._table_view.add_data_signal[int].connect(self._table_model.add_data)
        self._table_view.remove_row_signal[int].connect(self._table_model.remove_data)
        self._table_view.load_data_signal.connect(self._table_model.load_txt)
        self._table_view.save_data_signal.connect(self._table_model.save_txt)

    def value_changed(self, param):
        if param.name() == 'table':
            self.evaluate_nsteps()
        elif param.name() == 'send_points':
            if param.value():
                self.emit_positions()
                param.setValue(False)
        elif param.name() == 'show_points':
            if param.value():
                self.show_positions()
                param.setValue(False)

    def show_positions(self):
        widget = QtWidgets.QWidget()
        viewer = Viewer1D(widget)
        viewer.show_data([self.update_steps_calculation()])
        dialog('Positions to be send to Tabular Scan', '', widget)

    def evaluate_nsteps(self):
        Nsteps = 1
        for ind, data in enumerate(self._table_model.raw_data):
            if self._table_model.is_checked(ind):
                Nsteps += int((data[1] - data[0]) / data[2])
        self.settings.child('npts').setValue(Nsteps)

    def update_steps_calculation(self):
        init = False
        values = np.array([])
        for ind, data in enumerate(self._table_model.raw_data):
            if not init and self._table_model.is_checked(ind):
                values = utils.linspace_step(*data)
                init = True
            elif self._table_model.is_checked(ind):
                values = np.concatenate((values, utils.linspace_step(*data)))
        return values

    @property
    def view(self):
        return self._table_view

def print_positions(positions: np.ndarray):
    print(positions)
    print(f'the shape is {positions.shape} and the size {positions.size}')

def main():
    import sys
    app = QtWidgets.QApplication(sys.argv)
    dockarea = DockArea()
    prog = StepsSequencer(dockarea)
    prog.positions_signal.connect(print_positions)
    dockarea.show()
    sys.exit(app.exec_())

if __name__ == '__main__':

    main()


#!/usr/bin/env python
# File for custom messages etc

import rospy
import numpy as np
from std_msgs.msg import String
from sensor_msgs.msg import Imu
from geometry_msgs.msg import Pose
from std_msgs.msg import Header
from darknet_ros_msgs.msg import BoundingBoxes
from std_msgs.msg import Float32MultiArray
from std_msgs.msg import MultiArrayDimension

def Mat_buildROS(matrixDat): # Converts numpy array to ROS Array
        temp=Float32MultiArray()
        MatSize=matrixDat.shape[0]*matrixDat.shape[1]
        temp.data=matrixDat.reshape([MatSize])
        temp.layout.data_offset=0
        temp.layout.dim=[MultiArrayDimension(), MultiArrayDimension()]
        temp.layout.dim[0].label="Dim0"
        temp.layout.dim[1].label="Dim1"
        temp.layout.dim[0].size=matrixDat.shape[0]
        temp.layout.dim[1].size=matrixDat.shape[1]
        temp.layout.dim[0].stride=MatSize
        temp.layout.dim[1].stride=matrixDat.shape[1]
        return temp

def Mat_extractROS(MultiArrMsg): # Extracts numpy array from ROS MultiArray type  (for 2D Arrays)
    temp=np.array(MultiArrMsg.data)
    temp=temp.reshape((MultiArrMsg.layout.dim[0].size,MultiArrMsg.layout.dim[1].size))
    return temp

class CamObj:
    def __init__(self):
        self.stamp= Header().stamp # Gives time in nanoseconds
        self.xmin=0
        self.xmax=0
        self.ymin=0 # Location of the center of the box
        self.ymax=0
        # self.Area=[]
        # self.Ratio=[]
        # self.Position=Pose().position # To be calculated later, if req
        self.id=[] #ID of object, person=0, bicycle=1, all other veh =2
        self.confidence=[] # Probability of detection
class RadarObj:
    def __init__(self):
        self.header=Header() # Gives time in nanoseconds
        self.vx=[] #Relative Velocity, so have to ADD vehicle velocity.
        self.vy=[]
        self.vx_comp=[]
        self.vy_comp=[]
        self.pose=Pose() # Also relative distances from ego frame
class RadarObjMKZ:
    def __init__(self):
        self.id=0
        self.header=Header() # Gives time in nanoseconds
        self.vx=0.0 #Relative Velocity, so have to ADD vehicle velocity.
        self.vy=0.0
        self.vx_comp=0.0
        self.vy_comp=0.0
        self.pose=Pose() # Also relative distances from ego frame


from styx_msgs.msg import TrafficLight
#from pathlib import Path
import rospy
import tensorflow as tf
import cv2
import numpy as np
import os
import yaml

NUM_CLASSES = 4
MIN_SCORE_THR = .4

class TLClassifier(object):
    def __init__(self):
        # load classifier
        self.light_state = TrafficLight.UNKNOWN

        graph_to_load = 'frozen_inference_graph.pb'

        # Choose model for simulator or for real driving
        # if self.is_real:
        config_string = rospy.get_param("/traffic_light_config")
        self.config = yaml.load(config_string)
        self.is_real=self.config['is_site']
        if self.is_real:
            model_name = 'real_ssd_model_tf_1_4'
            rospy.loginfo("In real site environment...use {}/{}".format(
                model_name, graph_to_load))
        else:
            model_name = 'ssd_model_10000_tf_1_4'
            rospy.loginfo("In simulator environment...use {}/{}".format(
                model_name, graph_to_load))

        #p = Path(__file__).parents[4]
        #model_path = str(p) + '/traffic_light_classifier/' + model_name + '/' + graph_to_load
        model_path = '../../../traffic_light_classifier/' + model_name + '/' + graph_to_load
        rospy.logwarn("model_path={}".format(model_path))

        # Load saved model
        self.detection_graph = tf.Graph()
        with self.detection_graph.as_default():
            od_graph_def = tf.GraphDef()
            with tf.gfile.GFile(model_path, 'rb') as fid:
                serialized_graph = fid.read()
                od_graph_def.ParseFromString(serialized_graph)
                tf.import_graph_def(od_graph_def, name='')

        rospy.loginfo("TL Classifier ---> Model Loaded!")

        # Tensorflow session for detection
        config = tf.ConfigProto()
        config.gpu_options.allow_growth = True
        self.sess = tf.Session(graph=self.detection_graph, config=config)

        # Input and output Tensors for detection_graph
        self.image_tensor = self.detection_graph.get_tensor_by_name('image_tensor:0')

        self.num_detections = self.detection_graph.get_tensor_by_name('num_detections:0')
        self.detection_scores = self.detection_graph.get_tensor_by_name('detection_scores:0')
        self.detection_classes = self.detection_graph.get_tensor_by_name('detection_classes:0')
        self.detection_boxes = self.detection_graph.get_tensor_by_name('detection_boxes:0')

        self.category_index = {1: {'id': 1, 'name': 'Green'}, 2: {'id': 2, 'name': 'Red'}, 3: {'id': 3, 'name': 'Yellow'}, 4: {'id': 4, 'name': 'off'}}

    def get_classification(self, image):
        """Determines the color of the traffic light in the image
        Args:
            image (cv::Mat): image containing the traffic light
        Returns:
            int: ID of traffic light color (specified in styx_msgs/TrafficLight)
        """

        # TODO implement light color prediction
        # Preparing image
        image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        image_np = np.expand_dims(image_rgb, axis=0)

        # Detection
        with self.detection_graph.as_default():
            (det_boxes, det_scores, det_classes, num) = self.sess.run([self.detection_boxes, self.detection_scores,
                self.detection_classes, self.num_detections],
                feed_dict={self.image_tensor: image_np})

        scores = np.squeeze(det_scores)
        classes = np.squeeze(det_classes).astype(np.int32)
        boxes = np.squeeze(det_boxes)

        total_scores = { "Red": 0, "Yellow": 0, "Green": 0, "off": 0}

        count = 0
        for i in range(0, num):
            if scores is not None:
                score = scores[i]
                if score > MIN_SCORE_THR:
                    count += 1
                    class_name = self.category_index[classes[i]]['name']
                    total_scores[class_name] += score

        max_score = 0
        category = 'off'
        print(total_scores)
        for key in total_scores.keys():
            if count > 0:
                total_scores[key] /= (count * 1.0)

            if total_scores[key] > max_score:
                max_score = total_scores[key]
                category = key

        if category == 'Red':
            self.light_state = TrafficLight.RED
        elif category == 'Yellow':
            self.light_state = TrafficLight.YELLOW
        elif category == 'Green':
            self.light_state = TrafficLight.GREEN
        elif category=='off':
            self.light_state = TrafficLight.UNKNOWN
        if category=='off':
            category='Unknown'
        rospy.loginfo("TL Classifier ----> Detected TL state:" + category)
        return self.light_state


# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import sys
import os
from math import pow
import skimage.io
from skimage import transform as tf

caffe_root = '/home/lisheng/caffe/'
sys.path.insert(0, caffe_root + 'python')
# sys.path.append('/home/lisheng/caffe/python')
import caffe

from nms import nms_average, nms_max

# caffe.set_device(1)
# caffe.set_mode_gpu()

# Model related:
model_path = 'D:/caffe/人脸检测，特征点标定caffe实现/DeepFace-master/FaceDetection/try1_4/'
model_define= model_path+'deploy.prototxt'
model_weight =model_path+'snapshot_iter_100000.caffemodel'
model_define_fc =model_path+'deploy_fc.prototxt'
model_weight_fc =model_path+'snapshot_iter_100000_fc.caffemodel'

channel = 3
raw_scale = 255.0
face_w = 48
stride = 16
cellSize = face_w
threshold = 0.95
factor = 0.793700526 # 缩小因子

map_idx = 0
params = ['deepid', 'fc7']
params_fc =  ['deepid-conv', 'fc7-conv']

def generateBoundingBox(featureMap, scale):
    """

    :param featureMap: 特征图
    :param scale: 尺度
    :return: 生成窗口
    """

    boundingBox = []
    for (x,y), prob in np.ndenumerate(featureMap):
        if prob >= threshold:
            # 映射到原始的图像中的大小
            x = x-1
            y = y-1
            boundingBox.append([float(stride * y) / scale, float(stride * x) / scale,
                              float(stride * y + cellSize - 1) / scale, float(stride * x + cellSize - 1) / scale, prob])
            #boundingBox.append([float(stride * y-cellSize/2.0)/scale, float(stride *x -cellSize/2.0)/scale,
            #                   float(stride * y + cellSize/2.0 - 1)/scale, float(stride * x + cellSize/2.0 - 1)/scale, prob])
    return boundingBox

def convert_full_conv(model_define, model_weight, model_define_fc, model_weight_fc):
    """

    :param model_define: 二分类网络定义文件
    :param model_weight: 二分类网络训练好的参数
    :param model_define_fc: 生成的全卷积网络定义文件
    :param model_weight_fc: 转化好的全卷积网络的参数
    :return: 将原始网络转换为全卷积模型
    """

    net = caffe.Net(model_define, model_weight, caffe.TEST)
    fc_params = {pr: (net.params[pr][0].data, net.params[pr][1].data) for pr in params}
    net_fc = caffe.Net(model_define_fc, model_weight, caffe.TEST)
    conv_params = {pr: (net_fc.params[pr][0].data, net_fc.params[pr][1].data) for pr in params_fc}
    for pr, pr_conv in zip(params, params_fc):
        conv_params[pr_conv][0].flat = fc_params[pr][0].flat  # flat unrolls the arrays
        conv_params[pr_conv][1][...] = fc_params[pr][1]
    net_fc.save(model_weight_fc)
    print('convert done!')
    return net_fc

def re_verify(net_vf, img):
    """

    :param net_vf:
    :param img:
    :return: 对检测到的目标框进行重新的验证
    """

    img = tf.resize(img, (face_w, face_w))
    transformer = caffe.io.Transformer({'data': net_vf.blobs['data'].data.shape})
    transformer.set_transpose('data', (2, 0, 1))
    transformer.set_channel_swap('data', (2, 1, 0))
    transformer.set_raw_scale('data', raw_scale)
    out = net_vf.forward_all(data=np.asarray([transformer.preprocess('data', img)]))
    # print(out['prob'])
    if out['prob'][0,map_idx] > threshold:
        return True
    else:
        return False

def face_detection_image(net, net_vf, image_name):
    """

    :param net:
    :param net_vf:
    :param image_name:
    :return: 检测单张人脸图像
    """

    scales = []
    imgs = skimage.io.imread(image_name)
    if imgs.ndim == 3:
        rows,cols,ch = imgs.shape
    else:
        rows,cols = imgs.shape
    # 计算需要的检测的尺度因子
    min = rows if  rows <= cols  else  cols
    max = rows if  rows >= cols  else  cols
    # 放大的尺度
    delim = 2500 / max
    while delim >= 1:
        scales.append(delim)
        delim = delim - 0.5
    # 缩小的尺度
    min = min * factor
    factor_count = 1
    while min >= face_w:
        scale = pow(factor, factor_count)
        scales.append(scale)
        min = min * factor
        factor_count += 1
    # scales.append(1)
    total_boxes = []
    # 显示热图用
    num_scale = len(scales)
    s1 = int(np.sqrt(num_scale)) + 1
    tt = 1
    plt.subplot(s1, s1 + 1, tt)
    plt.axis('off')
    plt.title("Input Image")
    im = caffe.io.load_image(image_name)
    plt.imshow(im)

    for scale in scales:
        w, h = int(rows * scale), int(cols * scale)
        scale_img = tf.resize(imgs, (w, h))
        # 更改网络输入data图像的大小
        net.blobs['data'].reshape(1, channel, w, h)
        # 转换结构
        transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
        # transformer.set_mean('data', np.load(caffe_root + 'python/caffe/imagenet/ilsvrc_2012_mean.npy').mean(1).mean(1))
        transformer.set_transpose('data', (2, 0, 1))
        transformer.set_channel_swap('data', (2, 1, 0))
        transformer.set_raw_scale('data', raw_scale)
        # 前馈一次
        out = net.forward_all(data=np.asarray([transformer.preprocess('data', scale_img)]))
        # 显示热图用
        tt = tt+1
        plt.subplot(s1, s1 + 1, tt)
        plt.axis('off')
        plt.title("sacle: " + "%.2f" %scale)
        plt.imshow(out['prob'][0, map_idx])

        boxes = generateBoundingBox(out['prob'][0, map_idx], scale)
        if boxes:
            total_boxes.extend(boxes)
    # 非极大值抑制
    boxes_nms = np.array(total_boxes)
    true_boxes1 = nms_max(boxes_nms, overlapThresh=0.3)
    true_boxes = nms_average(np.array(true_boxes1), overlapThresh=0.07)

    plt.savefig('heatmap/' + image_name.split('/')[-1])
    # 在图像中画出检测到的人脸框
    fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(6, 6))
    ax.imshow(imgs)
    for box in true_boxes:
        im_crop = im[box[0]: box[2],box[1]: box[3], : ]
        if im_crop.shape[0] == 0 or im_crop.shape[1] == 0:
            continue
        if re_verify(net_vf, im_crop) is True:
            rect = mpatches.Rectangle((box[0], box[1]), box[2] - box[0], box[3] - box[1],
                                      fill=False, edgecolor='red', linewidth=1)
            ax.text(box[0], box[1] + 20, "{0:.3f}".format(box[4]), color='white', fontsize=6)
            ax.add_patch(rect)
    plt.savefig('result/' + image_name.split('/')[-1])
    plt.close()
    return out['prob'][0,map_idx]

if __name__ == "__main__":
    if not os.path.isfile(model_weight_fc):
        net_fc = convert_full_conv(model_define, model_weight, model_define_fc, model_weight_fc)
    else:
        net_fc = caffe.Net(model_define_fc, model_weight_fc, caffe.TEST)
    net_vf = caffe.Net(model_define, model_weight, caffe.TEST)
    for i in range(210):
        image_name = 'D:/caffe/人脸检测，特征点标定caffe实现/DeepFace-master/FaceDetection/baseline/' + str(i + 1) + '.jpg'
        print(i)
        fm = face_detection_image(net_fc, net_vf, image_name)
        plt.close('all')


"""Evaluation

"""

from collections import defaultdict as dd
import logging
import math
import sys

import subprocess

import codecs
import numpy as np

import os

import dynet

from toolkit.joint_ner_and_md_model import MainTaggerModel
from utils import eval_script, iobes_iob, eval_logs_dir
from utils.loader import prepare_datasets, extract_mapping_dictionaries_from_model

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("eval")

def eval_with_specific_model(model,
                             epoch,
                             datasets_to_be_predicted,
                             return_datasets_with_predicted_labels=False):

    # type: (MainTaggerModel, int, dict, bool) -> object
    eval_dir = eval_logs_dir
    batch_size = 1 # model.parameters['batch_size'] TODO: switch back for new models.
    integration_mode = model.parameters['integration_mode']
    active_models = model.parameters['active_models']
    id_to_tag = model.id_to_tag
    tag_scheme = model.parameters['t_s']

    f_scores = {"ner":{}}
    # dataset_labels = ["dev", "test", "yuret"]
    # dataset_labels = [map(lambda purpose: label+"_"+purpose, datasets_to_be_predicted[label].keys())
    #                   for label in datasets_to_be_predicted.keys()]

    # total_correct_disambs = {dataset_label: 0 for dataset_label in dataset_labels}
    # total_disamb_targets = {dataset_label: 0 for dataset_label in dataset_labels}

    total_correct_disambs = {label: {purpose: 0
                                     for purpose in list(datasets_to_be_predicted[label].keys())}
                             for label in list(datasets_to_be_predicted.keys())}

    total_disamb_targets = {label: {purpose: 0
                                     for purpose in list(datasets_to_be_predicted[label].keys())}
                             for label in list(datasets_to_be_predicted.keys())}

    if active_models in [1, 2, 3]:

        detailed_correct_disambs = {label: {purpose: dd(int)
                                        for purpose in list(datasets_to_be_predicted[label].keys())}
                                for label in list(datasets_to_be_predicted.keys())}

        detailed_total_target_disambs = {label: {purpose: dd(int)
                                        for purpose in list(datasets_to_be_predicted[label].keys())}
                                for label in list(datasets_to_be_predicted.keys())}

    datasets_with_predicted_labels = {label: {purpose: {}
                                        for purpose in list(datasets_to_be_predicted[label].keys())}
                                for label in list(datasets_to_be_predicted.keys())}

    # for dataset_label, dataset_as_list in datasets_to_be_predicted:
    for label in list(datasets_to_be_predicted.keys()):
        for purpose in list(datasets_to_be_predicted[label].keys()):

            dataset_as_list = datasets_to_be_predicted[label][purpose]

            if len(dataset_as_list) == 0:
                print("Skipping to evaluate %s dataset as it is empty" % (label+"_"+purpose))
                total_correct_disambs[label][purpose] = -1
                total_disamb_targets[label][purpose] = 1
                continue

            print("Starting to evaluate %s dataset" % (label+"_"+purpose))
            predictions = []
            n_tags = len(id_to_tag)
            count = np.zeros((n_tags, n_tags), dtype=np.int32)

            n_batches = int(math.ceil(float(len(dataset_as_list)) / batch_size))

            print("dataset_label: %s" % (label+"_"+purpose))
            print(("n_batches: %d" % n_batches))

            for batch_idx in range(n_batches):
                # print("batch_idx: %d" % batch_idx)
                sys.stdout.write(". ")
                sys.stdout.flush()

                sentences_in_the_batch = dataset_as_list[
                                         (batch_idx * batch_size):((batch_idx + 1) * batch_size)]

                for sentence in sentences_in_the_batch:
                    dynet.renew_cg()

                    sentence_length = len(sentence['word_ids'])

                    if active_models in [2, 3] and label in "ner md".split(" "):
                        selected_morph_analyzes, decoded_tags = model.predict(sentence)
                    elif active_models in [1] and label == "md":
                        selected_morph_analyzes, _ = model.predict(sentence)
                    elif active_models in [0] and label == "ner":
                        _, decoded_tags = model.predict(sentence)

                    if active_models in [0, 2, 3] and label == "ner": # i.e. except MD
                        p_tags = [id_to_tag[p_tag] for p_tag in decoded_tags]
                        r_tags = [id_to_tag[r_tag] for r_tag in sentence['tag_ids']]
                        if tag_scheme == 'iobes':
                            p_tags = iobes_iob(p_tags)
                            r_tags = iobes_iob(r_tags)

                        for i, (y_pred, y_real) in enumerate(
                                zip(decoded_tags, sentence['tag_ids'])):
                            new_line = " ".join([sentence['str_words'][i]] + [r_tags[i], p_tags[i]])
                            predictions.append(new_line)
                            count[y_real, y_pred] += 1
                        predictions.append("")

                    if active_models in [1, 2, 3] and label == "md":
                        n_correct_morph_disambs = \
                            sum([x == y for x, y, z in zip(selected_morph_analyzes,
                                                        sentence['golden_morph_analysis_indices'],
                                                        sentence['morpho_analyzes_tags']) if len(z) > 1])
                        total_correct_disambs[label][purpose] += n_correct_morph_disambs
                        total_disamb_targets[label][purpose] += sum([1 for el in sentence['morpho_analyzes_tags'] if len(el) > 1])
                        for key, value in [(len(el), x == y) for el, x, y in zip(sentence['morpho_analyzes_tags'],
                                                               selected_morph_analyzes,
                                                               sentence['golden_morph_analysis_indices'])]:
                            if value:
                                detailed_correct_disambs[label][purpose][key] += 1
                            detailed_total_target_disambs[label][purpose][key] += 1
                        # total_possible_analyzes += sum([len(el) for el in sentence['morpho_analyzes_tags'] if len(el) > 1])

            print("")

            if active_models in [0, 2, 3] and label == "ner":
                # Write predictions to disk and run CoNLL script externally
                eval_id = np.random.randint(1000000, 2000000)
                output_path = os.path.join(eval_dir,
                                           "%s.eval.%i.epoch-%04d.output" % (
                                               (label + "_" + purpose), eval_id, epoch))
                scores_path = os.path.join(eval_dir,
                                           "%s.eval.%i.epoch-%04d.scores" % (
                                               (label + "_" + purpose), eval_id, epoch))
                with codecs.open(output_path, 'w', 'utf8') as f:
                    f.write("\n".join(predictions))

                # os.system(command_string)
                # sys.exit(0)
                # with open(output_path, "r", encoding="utf-8") as output_path_f:
                # try:
                from evaluation.conlleval import evaluate as conll_evaluate, report as conll_report
                with open(output_path, "r") as output_path_f, open(scores_path, "w") as scores_path_f:
                    print("Evaluating the %s dataset with conlleval script's Python implementation" % (label + "_" + purpose))
                    counts = conll_evaluate(output_path_f)
                    eval_script_output = conll_report(counts, out=scores_path_f)
                # print("Evaluating the %s dataset with conlleval script runner" % (label + "_" + purpose))
                # command_string = "%s %s %s" % (eval_script, output_path, scores_path)
                # print(command_string)
                # print("Will timeout in 30 seconds and set the F1-score to 0 for this eval.")
                # # eval_script_output = subprocess.check_output([eval_script], stdin=output_path_f, timeout=30)
                # eval_script_output = subprocess.check_output([eval_script, output_path, scores_path], timeout=30)
#                 except subprocess.TimeoutExpired as e:
#                     print(e)
#                     eval_script_output = b"""processed 0 tokens with 0 phrases; found: 0 phrases; correct: 0.
# accuracy:  0.0%; precision:  0.0%; recall:  0.0%; FB1:  0.0
# """
                eval_lines = [x.rstrip() for x in eval_script_output.decode("utf8").split("\n")]

                # CoNLL evaluation results
                # eval_lines = [l.rstrip() for l in codecs.open(scores_path, 'r', 'utf8')]
                for line in eval_lines:
                    print(line)
                f_scores["ner"][purpose] = float(eval_lines[1].split(" ")[-1])

            if active_models in [1, 2, 3]:
                for n_possible_analyzes in map(int, list(detailed_correct_disambs[label][purpose].keys())):
                    print("%s %d %d/%d" % ((label + "_" + purpose),
                                           n_possible_analyzes,
                                           detailed_correct_disambs[label][purpose][n_possible_analyzes],
                                           detailed_total_target_disambs[label][purpose][n_possible_analyzes]))

            if return_datasets_with_predicted_labels:
                datasets_with_predicted_labels[label][purpose] = predictions

    disambiguation_accuracies = {label: {} for label in list(datasets_to_be_predicted.keys())}
    if active_models in [0]:
        pass
    else:
        for label in list(datasets_to_be_predicted.keys()):
            for purpose in list(datasets_to_be_predicted[label].keys()):
                if total_disamb_targets[label][purpose] == 0:
                    total_correct_disambs[label][purpose] = -1
                    total_disamb_targets[label][purpose] = 1
                disambiguation_accuracies[label][purpose] = \
                    total_correct_disambs[label][purpose] / float(total_disamb_targets[label][purpose])

    return f_scores, disambiguation_accuracies, datasets_with_predicted_labels

def do_xnlp(models_dir_path, model_dir_path, model_epoch_dir_path):

    model, opts, parameters = initialize_model_with_pretrained_parameters(model_dir_path,
                                                                          model_epoch_dir_path,
                                                                          models_dir_path)

    print(opts)
    print(parameters)

    for arg_name in opts.__dict__.keys():
        if type(opts.__dict__[arg_name]) == str:
            opts.__dict__[arg_name] = opts.__dict__[arg_name].replace("/truba/home/ogungor/projects/research/datasets/joint_ner_dynet-manylanguages/",
                                                                  "/Users/onur/Desktop/projects/research/datasets-to-TRUBA/")

    print(opts)
    # Prepare the data
    # dev_data, dico_words_train, \
    # id_to_tag, tag_scheme, test_data, \
    # train_data, train_stats, word_to_id, \
    # yuret_test_data, yuret_train_data
    data_dict, id_to_tag, word_to_id, stats_dict, id_to_char, id_to_morpho_tag = prepare_datasets(model,
                                                     opts,
                                                     parameters,
                                                     for_training=False)

    return model, data_dict, id_to_tag, word_to_id, stats_dict, id_to_char, id_to_morpho_tag

def evaluate_model_dir_path(models_dir_path, model_dir_path, model_epoch_dir_path):

    model, opts, parameters = initialize_model_with_pretrained_parameters(model_dir_path,
                                                                          model_epoch_dir_path,
                                                                          models_dir_path)

    # Prepare the data
    dev_data, dico_words_train, \
    id_to_tag, tag_scheme, test_data, \
    train_data, train_stats, word_to_id, \
    yuret_test_data, yuret_train_data = prepare_datasets(model,
                                                         opts,
                                                         parameters,
                                                         for_training=False)

    datasets_to_be_tested = [("dev", dev_data),
                             ("test", test_data)]

    f_scores, morph_accuracies, _ = predict_tags_given_model_and_input(datasets_to_be_tested,
                                                                       model,
                                                                       return_result=False)

    print(f_scores)
    print(morph_accuracies)

def predict_sentences_given_model(sentences_string, model):
    """

    :type sentences_string: string
    :type model: MainTaggerModel
    :param model:
        Mappings must be loaded.
    """

    from utils import tokenize_sentences_string
    from utils.loader import load_sentences, prepare_dataset

    tokenized_sentences = tokenize_sentences_string(sentences_string)

    # print tokenized_sentences

    from utils.morph_analyzer_caller import get_morph_analyzes, create_single_word_single_line_format

    # "\n".join([" ".join(x) for x in tokenized_sentences])
    dataset_file_string = ""
    morph_analyzer_output_for_all_sentences = ""
    for tokenized_sentence in tokenized_sentences:
        morph_analyzer_output_for_a_single_sentence = get_morph_analyzes(" ".join(tokenized_sentence))
        morph_analyzer_output_for_all_sentences += morph_analyzer_output_for_a_single_sentence + "\n"
        # print string_output
        dataset_file_string += create_single_word_single_line_format(morph_analyzer_output_for_a_single_sentence,
                                                                       conll=True,
                                                                       for_prediction=True)

    dataset_file_string = dataset_file_string.decode('iso-8859-9')
    # import sys
    # sys.exit(1)

    # print sentences_data_string.split("\n")
    # We now have the input sentences in our native format
    train_sentences, _, _ = load_sentences(dataset_file_string.split("\n"),
                                           model.parameters["zeros"])

    char_to_id, id_to_char, id_to_morpho_tag, id_to_tag, id_to_word, morpho_tag_to_id, tag_to_id, word_to_id = \
        extract_mapping_dictionaries_from_model(model)

    _, _, _, sentences_data = prepare_dataset(
        train_sentences,
        word_to_id, char_to_id, tag_to_id, morpho_tag_to_id,
        model.parameters['lower'],
        model.parameters['mt_d'], model.parameters['mt_t'], model.parameters['mt_ci'],
        morpho_tag_separator=("+" if model.parameters['lang_name'] == "turkish" else "|")
    )

    f_scores, morph_accuracies, labeled_sentences = \
        predict_tags_given_model_and_input([('tagger_output', sentences_data)],
                                           model,
                                           return_result=True)

    print(labeled_sentences)
    return labeled_sentences, dataset_file_string

def predict_tags_given_model_and_input(datasets_to_be_tested,
                                       model,
                                       return_result=False):

    f_scores, morph_accuracies, labeled_sentences = eval_with_specific_model(model,
                                                                             -1,
                                                                             datasets_to_be_tested,
                                                                             return_result)
    return f_scores, morph_accuracies, labeled_sentences

def initialize_model_with_pretrained_parameters(model_dir_path, model_epoch_dir_path, models_dir_path):
    import os
    from utils import read_parameters_from_file
    parameters, opts = read_parameters_from_file(os.path.join(models_dir_path, model_dir_path, "parameters.pkl"),
                                                 os.path.join(models_dir_path, model_dir_path, "opts.pkl"))
    model = MainTaggerModel(models_path=models_dir_path,
                            model_path=model_dir_path,
                            model_epoch_dir_path=model_epoch_dir_path)
    # Build the model
    model.build(training=False, **parameters)
    model.reload(os.path.join(models_dir_path, model_dir_path, model_epoch_dir_path))
    return model, opts, parameters

def evaluate(sys_argv):

    from utils import read_args

    opts = read_args(args_as_a_list=sys_argv[1:])

    from utils.train import models_path

    evaluate_model_dir_path(
        models_dir_path=models_path,
        model_dir_path=opts.model_path,
        model_epoch_dir_path=opts.model_epoch_path
    )

def xnlp_experiments(sys_argv):

    from utils import read_args

    opts = read_args(args_as_a_list=sys_argv[1:], for_xnlp=True)

    from utils.train import models_path

    model, data_dict, id_to_tag, word_to_id, stats_dict = do_xnlp(
        models_dir_path=models_path,
        model_dir_path=opts.model_path,
        model_epoch_dir_path=opts.model_epoch_path
    )

def predict_from_stdin(sys_argv):

    from utils import read_args

    opts = read_args(args_as_a_list=sys_argv[1:])

    from utils.train import models_path

    model, opts, parameters = initialize_model_with_pretrained_parameters(opts.model_path,
                                                                          opts.model_epoch_path,
                                                                          models_path)

    line = sys.stdin.readline()
    while line:
        # "ali ata bak\ndeneme deneme"
        predict_sentences_given_model(line.decode("utf8"), model)
        line = sys.stdin.readline()


import sys, os, time
import numpy as np
import torch.nn as nn
import torch.nn.init as init
import torch.nn.functional as F
import torch.optim as optim

import pickle
import torch
from arguments_rl import get_args

from collections import deque
from rl_module.a2c_ppo_acktr.envs import make_vec_envs
from rl_module.a2c_ppo_acktr.storage import RolloutStorage
from rl_module.train_ppo import train_ppo

def main():

    # Arguments
    args = get_args()
    conv_experiment = [
        'atari',
    ]

    # Split
    ##########################################################################################################################33
    if args.approach == 'fine-tuning' or args.approach == 'ft-fix':
        log_name = '{}_{}_{}_{}'.format(args.date, args.experiment, args.approach,args.seed)
    elif args.approach == 'ewc' in args.approach:
        log_name = '{}_{}_{}_{}_lamb_{}'.format(args.date, args.experiment, args.approach, args.seed, args.ewc_lambda)
    elif args.approach == 'blip':
        log_name = '{}_{}_{}_{}_F_prior_{}'.format(args.date, args.experiment, args.approach, args.seed, args.F_prior)

    if args.experiment in conv_experiment:
        log_name = log_name + '_conv'

    ########################################################################################################################
    # Seed
    np.random.seed(args.seed)
    torch.manual_seed(args.seed)
    if torch.cuda.is_available():
        torch.cuda.manual_seed(args.seed)
    else:
        print('[CUDA unavailable]'); sys.exit()
    torch.backends.cudnn.deterministic = True
    torch.backends.cudnn.benchmark = False

    # Inits
    print('Inits...')
    torch.set_default_tensor_type('torch.cuda.FloatTensor')
    device = torch.device("cuda:0" if args.cuda else "cpu")

    taskcla = [(0,14), (1,18), (2,18), (3,18), (4,18), (5,6)]
    task_sequences = [(0, 'KungFuMasterNoFrameskip-v4'), (1, 'BoxingNoFrameskip-v4'),
                    (2, 'JamesbondNoFrameskip-v4'), (3, 'KrullNoFrameskip-v4'),
                    (4, 'RiverraidNoFrameskip-v4'), (5, 'SpaceInvadersNoFrameskip-v4')]

    # hard coded for atari environment
    obs_shape = (4,84,84)

    if args.approach == 'blip':
        from rl_module.ppo_model import QPolicy
        print('using fisher prior of: ', args.F_prior)
        actor_critic = QPolicy(obs_shape,
            taskcla,
            base_kwargs={'F_prior': args.F_prior, 'recurrent': args.recurrent_policy}).to(device)
    else:
        from rl_module.ppo_model import Policy
        actor_critic = Policy(obs_shape,
            taskcla,
            base_kwargs={'recurrent': args.recurrent_policy}).to(device)

    # Args -- Approach
    if args.approach == 'fine-tuning' or args.approach == 'ft-fix':
        from rl_module.ppo import PPO as approach

        agent = approach(actor_critic,
                args.clip_param,
                args.ppo_epoch,
                args.num_mini_batch,
                args.value_loss_coef,
                args.entropy_coef,
                lr=args.lr,
                eps=args.eps,
                max_grad_norm=args.max_grad_norm,
                use_clipped_value_loss=True)
    elif args.approach == 'ewc':
        from rl_module.ppo_ewc import PPO_EWC as approach

        agent = approach(
            actor_critic,
            args.clip_param,
            args.ppo_epoch,
            args.num_mini_batch,
            args.value_loss_coef,
            args.entropy_coef,
            lr=args.lr,
            eps=args.eps,
            max_grad_norm=args.max_grad_norm,
            use_clipped_value_loss=True,
            ewc_lambda= args.ewc_lambda,
            online = args.ewc_online)

    elif args.approach == 'blip':
        from rl_module.ppo_blip import PPO_BLIP as approach

        agent = approach(
            actor_critic,
            args.clip_param,
            args.ppo_epoch,
            args.num_mini_batch,
            args.value_loss_coef,
            args.entropy_coef,
            lr=args.lr,
            eps=args.eps,
            max_grad_norm=args.max_grad_norm,
            use_clipped_value_loss=True)

    ########################################################################################################################

    tr_reward_arr = []
    te_reward_arr = {}

    for _type in (['mean', 'max', 'min']):
        te_reward_arr[_type] = {}
        for idx in range(len(taskcla)):
            te_reward_arr[_type]['task' + str(idx)] = []

    for task_idx,env_name in task_sequences:
        print(env_name)
        # renew optimizer
        agent.renew_optimizer()

        envs = make_vec_envs(env_name, args.seed, args.num_processes,
                             args.gamma, args.log_dir, device, False)
        obs = envs.reset()

        rollouts = RolloutStorage(args.num_steps, args.num_processes,
                                      obs_shape, envs.action_space,
                                      actor_critic.recurrent_hidden_state_size)

        rollouts.obs[0].copy_(obs)
        rollouts.to(device)

        episode_rewards = deque(maxlen=10)
        num_updates = int(args.num_env_steps) // args.num_steps // args.num_processes

        train_ppo(actor_critic, agent, rollouts, task_idx, env_name, task_sequences, envs, obs_shape, args,
                  episode_rewards, tr_reward_arr, te_reward_arr, num_updates, log_name, device)

        # post-processing
        if args.approach == 'fine-tuning':
            if args.single_task == True:
                envs.close()
                break
            else:
                envs.close()
        elif args.approach == 'ft-fix':
            # fix the backbone
            for param in actor_critic.features.parameters():
                param.requires_grad = False
            if args.single_task == True:
                envs.close()
                break
            else:
                envs.close()
        elif args.approach == 'ewc':
            agent.update_fisher(rollouts, task_idx)
            envs.close()
        elif args.approach == 'blip':
            agent.ng_post_processing(rollouts, task_idx)
            # save the model here so that bit allocation is saved
            save_path = os.path.join(args.save_dir, args.algo)
            torch.save(actor_critic.state_dict(),
                os.path.join(save_path, log_name + '_task_' + str(task_idx) + ".pth"))
            envs.close()

    ########################################################################################################################

if __name__ == '__main__':
    main()


import cv2
import os
import numpy as np
from PIL import Image
from tqdm import tqdm

def cv_img(img_path, target_path, target_txt):
    tf = open(target_txt, 'w')

    imgs_f = open(img_path, 'r')
    imgs = imgs_f.readlines()

    img_count = 70000
    for i in tqdm(imgs):
        path = i.strip().split(' ')[0]
        boxes = np.array([float(j) for j in i.strip().split(' ')[1:]]).reshape(-1, 4)

        img = cv2.imread(path)
        h, w, c = img.shape
        if h < w:
            image = np.array(Image.new("RGB", (2675,2000), (255,255,255)))
            image[0:h, 0:w, :] = img
            for col in range(6):
                for row in range(6):
                    box_list = []
                    img = image[row*208:row*208+960, col*343:col*343+960, :].copy()
                    for b in boxes:
                        if b[2] >= col*343 and b[2] <= col*343+960:
                            if b[3] >= row*208 and b[3] <= row*208+960:
                                box_list.append(b)
                            elif b[1] >= row*208 and b[1] <= row*208+960:
                                box_list.append(b)
                        elif b[0] >= col*343 and b[0] <= col*343+960:
                            if b[3] >= row*208 and b[3] <= row*208+960:
                                box_list.append(b)
                            elif b[1] >= row*208 and b[1] <= row*208+960:
                                box_list.append(b)

                    if len(box_list) == 0:
                        continue

                    box_list = np.array(box_list)
                    new_box_list = box_list.copy()
                    new_box_list[:, (0,2)] = new_box_list[:, (0,2)] - col*343
                    new_box_list[:, (1,3)] = new_box_list[:, (1,3)] - row*208
                    new_box_list = np.clip(new_box_list, 0., 960.)

                    box_keep = []
                    for ori_b, new_b in zip(box_list, new_box_list):
                        ori_w, ori_h = ori_b[2] - ori_b[0], ori_b[3] - ori_b[1]
                        new_w, new_h = new_b[2] - new_b[0], new_b[3] - new_b[1]
                        if new_w / ori_w < 0.5 and new_h / ori_h < 0.5:
                            continue
                        if new_w / ori_w < 0.35:
                            continue
                        if new_h / ori_h < 0.35:
                            continue
                        if new_w >= new_h:
                            if new_w / new_h < 3:
                                box_keep.append(new_b)
                        if new_w < new_h:
                            if new_h / new_w < 3:
                                box_keep.append(new_b)
                    box_keep = ' '.join([str(e) for e in np.array(box_keep).reshape(-1,)])
                    img_name = str(img_count).zfill(7) + '.png'
                    cv2.imwrite(os.path.join(target_path, img_name), img)
                    tf.write(img_name + ' ' + box_keep + '\n')
                    img_count += 1

                    # print(box_keep)
                    # for b in box_keep:
                    #     font = cv2.FONT_HERSHEY_SIMPLEX
                    #     cv2.rectangle(img, (int(b[0]), int(b[1])), (int(b[2]), int(b[3])), (0,255,255), 3)

                    # cv2.imshow('img', img)
                    # cv2.waitKey(0)
        else:
            image = np.array(Image.new("RGB", (2000,2675), (255,255,255)))
            image[0:h, 0:w, :] = img
            for col in range(6):
                for row in range(6):
                    box_list = []
                    img = image[row*343:row*343+960, col*208:col*208+960, :].copy()
                    for b in boxes:
                        if b[2] >= col*208 and b[2] <= col*208+960:
                            if b[3] >= row*343 and b[3] <= row*343+960:
                                box_list.append(b)
                            elif b[1] >= row*343 and b[1] <= row*343+960:
                                box_list.append(b)
                        elif b[0] >= col*208 and b[0] <= col*208+960:
                            if b[3] >= row*343 and b[3] <= row*343+960:
                                box_list.append(b)
                            elif b[1] >= row*343 and b[1] <= row*343+960:
                                box_list.append(b)

                    if len(box_list) == 0:
                        continue

                    box_list = np.array(box_list)
                    new_box_list = box_list.copy()
                    new_box_list[:, (0,2)] = new_box_list[:, (0,2)] - col*208
                    new_box_list[:, (1,3)] = new_box_list[:, (1,3)] - row*343
                    new_box_list = np.clip(new_box_list, 0., 960.)

                    box_keep = []
                    for ori_b, new_b in zip(box_list, new_box_list):
                        ori_w, ori_h = ori_b[2] - ori_b[0], ori_b[3] - ori_b[1]
                        new_w, new_h = new_b[2] - new_b[0], new_b[3] - new_b[1]
                        if new_w / ori_w < 0.5 and new_h / ori_h < 0.5:
                            continue
                        if new_w / ori_w < 0.35:
                            continue
                        if new_h / ori_h < 0.35:
                            continue
                        if new_w >= new_h:
                            if new_w / new_h < 3:
                                box_keep.append(new_b)
                        if new_w < new_h:
                            if new_h / new_w < 3:
                                box_keep.append(new_b)

                    box_keep = ' '.join([str(e) for e in np.array(box_keep).reshape(-1,)])
                    img_name = str(img_count).zfill(7) + '.png'
                    cv2.imwrite(os.path.join(target_path, img_name), img)
                    tf.write(img_name + ' ' + box_keep + '\n')
                    img_count += 1

                    # print(box_keep)
                    # for b in box_keep:
                    #     font = cv2.FONT_HERSHEY_SIMPLEX
                    #     cv2.rectangle(img, (int(b[0]), int(b[1])), (int(b[2]), int(b[3])), (0,255,255), 3)

                    # cv2.imshow('img', img)
                    # cv2.waitKey(0)

if __name__ == '__main__':
    img_path = '../../data/original_img/cv0123_and_aug0123.txt'
    target_path = '../../DataFountain/GLODON_ObjDet/cv_img'
    target_txt = '../../data/img_list/img_label_list.txt'
    cv_img(img_path, target_path, target_txt)

    img_path = '../../data/original_img/cv4_and_aug4.txt'
    target_path = '../../DataFountain/GLODON_ObjDet/c3s/cv_img'
    target_txt = '../../data/img_list/img_label_list_cv4aug4.txt'
    cv_img(img_path, target_path, target_txt)


from src.env_wrappers import wrap_dqn
from src.models import Nature
import tensorflow as tf
import numpy as np

nonlin_dict = {
    'elu': tf.nn.elu,
    'relu': tf.nn.relu,
    'sigmoid': tf.nn.sigmoid,
    'tanh': tf.nn.tanh
}

# If you add a new network you should add "string --> class" mapping here.
network_dict = {
    "Nature": Nature,
}

class Policy(object):
    def __init__(self, env, network, nonlin_name):
        # Size of the virtual batch
        self.vb_size = 128
        # Maximum length of each episode (in steps)
        self.max_episode_len = 25000
        # Nonlinearity used in the network
        self.nonlin = nonlin_dict[nonlin_name]

        self.vb = None

        # Apply standard reinforcement learning preprocessing pipeline.
        # to the input frames
        self.env = wrap_dqn(env)

        # Shapes of the input and output of the network.
        self.in_shape = list(self.env.observation_space.shape)
        self.out_num = self.env.action_space.n

        # is_training is set to True when we forward virtual batch at the beginning of each iteration.
        # This updates normalization statistics, is_training is set to False during episode evaluation.
        self.is_training = tf.placeholder(tf.bool, [], name="is_training")

        # Placeholder for the input state
        self.input_placeholder = tf.placeholder(tf.float32, [None] + self.in_shape, name='Input')

        # Create session for 1 CPU
        tf_config = tf.ConfigProto(inter_op_parallelism_threads=1, intra_op_parallelism_threads=1)
        self.sess = tf.Session(config=tf_config)

        # Output from the network, computed values for each action.
        # In each step we will execute action with the maximum value.
        NetworkClass = network_dict[network]
        self.action_op = NetworkClass(self.input_placeholder, self.out_num, self.nonlin, self.is_training)

        # Tensorflow operation to compute and save virtual batch normalization statistics.
        self.vb_op = tf.get_collection(tf.GraphKeys.UPDATE_OPS)

        self.sess.run(tf.global_variables_initializer())

        # Those variables will be updated using ES algorithm.
        self.parameters = tf.trainable_variables()

        # We need to save parameter shapes. Those are used when extracting parameters from flat array.
        self.parameter_shapes = [Policy.shape2int(p) for p in self.parameters]

        # Operations to assign new values to the parameters.
        self.parameters_placeholders = [tf.placeholder(dtype=tf.float32, shape=s) for s in self.parameter_shapes]
        self.set_parameters_ops = [par.assign(placeholder) for par, placeholder in
                                   zip(self.parameters, self.parameters_placeholders)]

    @staticmethod
    def shape2int(x):
        s = x.get_shape()
        return [int(si) for si in s]

    def get_vb(self):
        # Plays the game using random actions,
        # after each step if game is not done there is 1% probability
        # that the state will be saved in the reference batch.
        # Ends when enough samples were collected (128 by default).
        vb = []
        self.env.reset()
        while len(vb) < self.vb_size:
            # Apply random action and with 1% chance save this state.
            state, _, done, _ = self.env.step(np.random.randint(self.out_num))
            if done:
                self.env.reset()
            elif np.random.rand() < 0.01:
                vb.append(np.array(state))

        vb = np.asarray(vb)
        self.set_vb(vb)
        return vb

    def set_vb(self, vb):
        self.vb = vb
        # Computes normalization statistics using virtual batch.
        self.sess.run(self.vb_op, feed_dict={self.input_placeholder: self.vb, self.is_training: True})

    def get_parameters(self):
        # Extracts parameters from the network and returns flat 1D array with parameter values.
        parameters = self.sess.run(self.parameters)
        return np.concatenate([p.flatten() for p in parameters])

    def set_parameters(self, parameters):
        # Sets network parameters from flat 1D array with parameter values.
        feed_dict = {}
        current_position = 0
        for parameter_placeholder, shape in zip(self.parameters_placeholders, self.parameter_shapes):
            length = np.prod(shape)
            feed_dict[parameter_placeholder] = parameters[current_position:current_position+length].reshape(shape)
            current_position += length
        self.sess.run(self.set_parameters_ops, feed_dict=feed_dict)

        # We need to update normalization statistics each time new parameters are set.
        if self.vb is not None:
            self.sess.run(self.vb_op, feed_dict={self.input_placeholder: self.vb, self.is_training: True})

    def rollout(self, render=False):
        # Evaluates the policy for up to max_episode_len steps.
        ob = self.env.reset()
        ob = np.asarray(ob)
        t = 0
        rew_sum = 0
        for _ in range(self.max_episode_len):
            ac = self.sess.run(self.action_op, feed_dict={self.input_placeholder: [ob], self.is_training: False})
            ob, rew, done, _ = self.env.step(np.argmax(ac))
            ob = np.asarray(ob)
            rew_sum += rew
            t += 1
            if render:
                self.env.render()
            if done:
                break

        return rew_sum, t

# Wrapper for setting some parameters to 0 in specified layers.
# Was used to test how well the network works if we decrease the number of parameters.
class DropoutPolicy(Policy):
    def __init__(self, env, network, nonlin_name, seed=1, keep=0.01, layers=(6,)):
        super().__init__(env, network, nonlin_name)
        state = np.random.RandomState(seed)

        # Layers for which we apply dropout (index).
        self.layers = layers

        parameters = self.sess.run(self.parameters)

        # Mask will contain indices in par vector for which we do not apply dropout
        self.mask = []
        offset = 0
        for i, p in enumerate(parameters):
            size = np.prod([int(s) for s in p.shape])

            if i in layers:
                indices = state.choice(range(offset, offset + size), size=int(size*keep), replace=False)
                self.mask.extend(indices)
            else:
                self.mask.extend(range(offset, offset + size))
            offset += size

        # Ignore some parameters (Will set them to 0 and never update)
        self._parameters = np.zeros(offset)
        self._parameters[self.mask] = super().get_parameters()[self.mask]
        super().set_parameters(self._parameters)

    def get_parameters(self):
        return self._parameters[self.mask]

    def set_parameters(self, parameters):
        self._parameters[self.mask] = parameters
        super().set_parameters(self._parameters)