def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    dataBlobUrl = req.params.get('dataBlobUrl')
    if not dataBlobUrl:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            dataBlobUrl = req_body.get('dataBlobUrl')

    if dataBlobUrl:

        # Get Cognitive Services Environment Variables
        projectID = os.environ["projectID"]
        trainingKey = os.environ['trainingKey']
        predictionKey = os.environ['predictionKey']
        clientEndpoint = os.environ['clientEndpoint']


        trainer = CustomVisionTrainingClient(trainingKey, endpoint=clientEndpoint)
        iterations = trainer.get_iterations(projectID)
        if len(iterations) != 0:

            currentIteration = iterations[0]
            currentIterationName = currentIteration.publish_name

            httpEndpoint = clientEndpoint + "customvision/v3.0/Prediction/" + projectID + "/classify/iterations/" + currentIterationName + "/url"

            headers = {'Prediction-Key': predictionKey, 'Content-Type': 'application/json'}
            data = {"url": dataBlobUrl}
            response = requests.post(httpEndpoint, headers = headers,
                                    json = data)

            responseDictionary = response.json()
            Prediction = responseDictionary['predictions'][0]
            confidence = Prediction['probability']
            responseDictionary['confidence'] = confidence
                
            # Display the results.
            return func.HttpResponse(json.dumps(responseDictionary))

        else:
            return f'Model not trained.'
            # return func.HttpResponse("Model not trained.", status_code=400)
    else:
        return func.HttpResponse(
             "Please pass a dataBlobUrl on the query string or in the request body",
             status_code=400
        )
credentials = ApiKeyCredentials(in_headers={"Training-key": training_key})
train = CustomVisionTrainingClient(endpoint, credentials)
prediction_credentials = ApiKeyCredentials(
    in_headers={"Prediction-key": prediction_key})
predict = CustomVisionPredictionClient(endpoint, prediction_credentials)

#Gets the projects available
projects = train.get_projects()

#Finds the project used for HTN - Under projects
for p in projects:
    if p.name == "HandPredictionModel":
        project = p

#Gets the project q
iterations = train.get_iterations("<Project-ID>")

#Opens webcam
vidFeed = cv2.VideoCapture(0)

#Loop that occurs while the webcam is open
while (vidFeed.isOpened()):
    #Defining keypressed (waits and listens for key presses)
    keyPressed = cv2.waitKey(2)

    #Importing the code that detects the arduino Input

    #define frame as the frame of webcam feed
    ret, frame = vidFeed.read()

    #Changes the size of the image such that the aspect ratio is kept the same
예제 #3
0
        nfailed = len([i for i in upload_result.images if i.status != "OK"])

print("Training...")

iteration = trainer.train_project(project.id)
while iteration.status != "Completed":
    iteration = trainer.get_iteration(project.id, iteration.id)
    print("Training status: " + iteration.status)
    time.sleep(1)

# The iteration is now trained. Publish it to the project endpoint
trainer.publish_iteration(project.id, iteration.id, publish_iteration_name,
                          prediction_resource_id)
print("Done!")
liste = trainer.get_iterations(project.id)
print(liste[0].status)

# Now there is a trained endpoint that can be used to make a prediction
prediction_credentials = ApiKeyCredentials(
    in_headers={"Prediction-key": prediction_key})
predictor = CustomVisionPredictionClient(ENDPOINT, prediction_credentials)

test_image_url = "https://originaldataset.blob.core.windows.net/ambulance/4504435055132672.png"

results = predictor.classify_image_url(project.id, publish_iteration_name,
                                       test_image_url)

# Display the results.
for prediction in results.predictions:
    print("\t" + prediction.tag_name +
def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    try:
        data_url = req.params.get('ImageUrl')
        if not data_url:
            data_url = req.form.get('ImageUrl')

    except ValueError:
        return func.HttpResponse(
            "Please pass a ImageUrl on the query string or in the request body",
            status_code=400
        )


    if data_url:

        # Get Cognitive Services Environment Variables
        project_id = os.environ["ProjectID"]
        training_key = os.environ['TrainingKey']
        prediction_key = os.environ['PredictionKey']
        client_endpoint = os.environ['ClientEndpoint']


        trainer = CustomVisionTrainingClient(training_key, endpoint=client_endpoint)
        #predictor = CustomVisionPredictionClient(prediction_key, endpoint=client_endpoint)

        iterations = trainer.get_iterations(project_id)
        if len(iterations) != 0:

            # get the name of the current published iteration as that is required in the url
            current_iteration = iterations[0]
            current_iteration_name = current_iteration.publish_name
            #current_iteration_name = current_iteration.name

            # cannot use the client as it does not return detailed http response
            #results = predictor.classify_image_url(project_id, current_iteration_name, data_url)

            # format the url to call the custom vision model
            http_endpoint = client_endpoint + "customvision/v3.0/Prediction/" + project_id + "/classify/iterations/" + current_iteration_name + "/url"

            # add headers and body to the call and get the response
            headers = {'Prediction-Key': prediction_key, 'Content-Type': 'application/json'}
            data = {"url": data_url}
            response = requests.post(http_endpoint, headers = headers,
                                    json = data)

            # format the response to include the required json name 'confidence'
            response_dictionary = response.json()
            prediction = response_dictionary['predictions'][0]
            confidence = prediction['probability']
            #confidence = results.predictions[0].probability
            response_dictionary['confidence'] = confidence
    
            # return the json results of the object detection custom vision model.
            return func.HttpResponse(json.dumps(response_dictionary))

        else:
            return func.HttpResponse(
                "Model not trained.",
                status_code=400
            )
    else:
        return func.HttpResponse(
            "Please pass a ImageUrl on the query string or in the request body",
            status_code=400
        )
예제 #5
0
# Custom Vision modules
from azure.cognitiveservices.vision.customvision.training import CustomVisionTrainingClient
from msrest.authentication import ApiKeyCredentials

from cv_00_credentials import ENDPOINT
from cv_00_credentials import training_key
from cv_00_credentials import prediction_resource_id

credentials = ApiKeyCredentials(in_headers={"Training-key": training_key})
trainer = CustomVisionTrainingClient(ENDPOINT, credentials)

# It is just demo, we use first project in Custom Vison resource
project = trainer.get_projects()[0]
print('Project: ' + project.name)

# It is just demo, we use first iteration in Custom Vison resource
iteration = trainer.get_iterations(project.id)[0]

print('Iteration: ' + iteration.name)

published = trainer.publish_iteration(project.id, iteration.id, iteration.name,
                                      prediction_resource_id)
예제 #6
0
class Classifier:
    """
        Class for interacting with Custom Vision. Contatins three key methods:
            - predict_imgage() / predicts a an image
            - upload_images() / reads image URLs from Blob Storage and uploads to Custom Vision
            - train() / trains a model
    """
    def __init__(self) -> None:
        """
            Reads configuration file
            Initializes connection to Azure Custom Vision predictor and training resources.

            Parameters:
            blob_service_client: Azure Blob Service interaction client

            Returns:
            None
        """
        self.ENDPOINT = Keys.get("CV_ENDPOINT")
        self.project_id = Keys.get("CV_PROJECT_ID")
        self.prediction_key = Keys.get("CV_PREDICTION_KEY")
        self.training_key = Keys.get("CV_TRAINING_KEY")
        self.base_img_url = Keys.get("BASE_BLOB_URL")
        self.prediction_resource_id = Keys.get("CV_PREDICTION_RESOURCE_ID")

        self.prediction_credentials = ApiKeyCredentials(
            in_headers={"Prediction-key": self.prediction_key})
        self.predictor = CustomVisionPredictionClient(
            self.ENDPOINT, self.prediction_credentials)
        self.training_credentials = ApiKeyCredentials(
            in_headers={"Training-key": self.training_key})
        self.trainer = CustomVisionTrainingClient(self.ENDPOINT,
                                                  self.training_credentials)
        connect_str = Keys.get("BLOB_CONNECTION_STRING")
        self.blob_service_client = BlobServiceClient.from_connection_string(
            connect_str)
        try:
            # get all project iterations
            iterations = self.trainer.get_iterations(self.project_id)
            # find published iterations
            puplished_iterations = [
                iteration for iteration in iterations
                if iteration.publish_name != None
            ]
            # get the latest published iteration
            puplished_iterations.sort(key=lambda i: i.created)
            self.iteration_name = puplished_iterations[-1].publish_name

            with api.app.app_context():
                models.update_iteration_name(self.iteration_name)
        except Exception as e:
            logging.info(e)
            self.iteration_name = "iteration1"

    def predict_image_url(self, img_url: str) -> Dict[str, float]:
        """
            Predicts label(s) of Image read from URL.

            Parameters:
            img_url: Image URL

            Returns:
            (prediction (dict[str,float]): labels and assosiated probabilities,
            best_guess: (str): name of the label with highest probability)
        """
        with api.app.app_context():
            self.iteration_name = models.get_iteration_name()
        res = self.predictor.classify_image_url(self.project_id,
                                                self.iteration_name, img_url)
        pred_kv = dict([(i.tag_name, i.probability) for i in res.predictions])
        best_guess = max(pred_kv, key=pred_kv.get)

        return pred_kv, best_guess

    def predict_image(self, img) -> Dict[str, float]:
        """
            Predicts label(s) of Image read from URL.
            ASSUMES:
            -image of type .png
            -image size less than 4MB
            -image resolution at least 256x256 pixels

            Parameters:
            img_url: .png file

            Returns:
            (prediction (dict[str,float]): labels and assosiated probabilities,
            best_guess: (str): name of the label with highest probability)
        """
        with api.app.app_context():
            self.iteration_name = models.get_iteration_name()
        res = self.predictor.classify_image_with_no_store(
            self.project_id, self.iteration_name, img)
        # reset the file head such that it does not affect the state of the file handle
        img.seek(0)
        pred_kv = dict([(i.tag_name, i.probability) for i in res.predictions])
        best_guess = max(pred_kv, key=pred_kv.get)
        return pred_kv, best_guess

    def predict_image_by_post(self, img) -> Dict[str, float]:
        """
            Predicts label(s) of Image read from URL.
            ASSUMES:
            -image of type .png
            -image size less than 4MB
            -image resolution at least 256x256 pixels

            Parameters:
            img_url: .png file

            Returns:
            (prediction (dict[str,float]): labels and assosiated probabilities,
            best_guess: (str): name of the label with highest probability)
        """

        headers = {
            'content-type': 'application/octet-stream',
            "prediction-key": self.prediction_key
        }
        res = requests.post(Keys.get("CV_PREDICTION_ENDPOINT"),
                            img.read(),
                            headers=headers).json()
        img.seek(0)
        pred_kv = dict([(i["tagName"], i["probability"])
                        for i in res["predictions"]])
        best_guess = max(pred_kv, key=pred_kv.get)
        return pred_kv, best_guess

    def __chunks(self, lst, n):
        """
            Helper method used by upload_images() to upload URL chunks of 64, which is maximum chunk size in Azure Custom Vision.
        """
        for i in range(0, len(lst), n):
            yield lst[i:i + n]

    def upload_images(self, labels: List, container_name) -> None:
        """
            Takes as input a list of labels, uploads all assosiated images to Azure Custom Vision project.
            If label in input already exists in Custom Vision project, all images are uploaded directly.
            If label in input does not exist in Custom Vision project, new label (Tag object in Custom Vision) is created before uploading images

            Parameters:
            labels (str[]): List of labels

            Returns:
            None
        """
        url_list = []
        existing_tags = list(self.trainer.get_tags(self.project_id))

        try:
            container = self.blob_service_client.get_container_client(
                container_name)
        except Exception as e:
            print(
                "could not find container with CONTAINER_NAME name error: ",
                str(e),
            )

        for label in labels:
            # check if input has correct type
            if not isinstance(label, str):
                raise Exception("label " + str(label) + " must be a string")

            tag = [t for t in existing_tags if t.name == label]
            # check if tag already exists
            if len(tag) == 0:
                try:
                    tag = self.trainer.create_tag(self.project_id, label)
                    print("Created new label in project: " + label)
                except Exception as e:
                    print(e)
                    continue
            else:
                tag = tag[0]

            blob_prefix = f"{label}/"
            blob_list = container.list_blobs(name_starts_with=blob_prefix)

            if not blob_list:
                raise AttributeError("no images for this label")

            # build correct URLs and append to URL list
            for blob in blob_list:
                blob_url = f"{self.base_img_url}/{container_name}/{blob.name}"
                url_list.append(
                    ImageUrlCreateEntry(url=blob_url, tag_ids=[tag.id]))

        # upload URLs in chunks of 64
        print("Uploading images from blob to CV")
        img_f = 0
        img_s = 0
        img_d = 0
        itr_img = 0
        chunks = self.__chunks(url_list, setup.CV_MAX_IMAGES)
        num_imgs = len(url_list)
        error_messages = set()
        for url_chunk in chunks:
            upload_result = self.trainer.create_images_from_urls(
                self.project_id, images=url_chunk)
            if not upload_result.is_batch_successful:
                for image in upload_result.images:
                    if image.status == "OK":
                        img_s += 1
                    elif image.status == "OKDuplicate":
                        img_d += 1
                    else:
                        error_messages.add(image.status)
                        img_f += 1

                    itr_img += 1
            else:
                batch_size = len(upload_result.images)
                img_s += batch_size
                itr_img += batch_size

            prc = itr_img / num_imgs
            print(
                f"\t succesfull: \033[92m {img_s:5d} \033]92m \033[0m",
                f"\t duplicates: \033[33m {img_d:5d} \033]33m \033[0m",
                f"\t failed: \033[91m {img_f:5d} \033]91m \033[0m",
                f"\t [{prc:03.2%}]",
                sep="",
                end="\r",
                flush=True,
            )

        print()
        if len(error_messages) > 0:
            print("Error messages:")
            for error_message in error_messages:
                print(f"\t {error_message}")

    def get_iteration(self):
        iterations = self.trainer.get_iterations(self.project_id)
        iterations.sort(key=(lambda i: i.created))
        newest_iteration = iterations[-1]
        return newest_iteration

    def delete_iteration(self) -> None:
        """
            Deletes the oldest iteration in Custom Vision if there are 11 iterations.
            Custom Vision allows maximum 10 iterations in the free version.
        """
        iterations = self.trainer.get_iterations(self.project_id)
        if len(iterations) >= setup.CV_MAX_ITERATIONS:
            iterations.sort(key=lambda i: i.created)
            oldest_iteration = iterations[0].id
            self.trainer.unpublish_iteration(self.project_id, oldest_iteration)
            self.trainer.delete_iteration(self.project_id, oldest_iteration)

    def train(self, labels: list) -> None:
        """
            Trains model on all labels specified in input list, exeption is raised by self.trainer.train_projec() is asked to train on non existent labels.
            Generates unique iteration name, publishes model and sets self.iteration_name if successful.
            Parameters:
            labels (str[]): List of labels
        """
        try:
            email = Keys.get("EMAIL")
        except Exception:
            print("No email found, setting to empty")
            email = ""

        self.delete_iteration()
        print("Training...")
        iteration = self.trainer.train_project(
            self.project_id,
            reserved_budget_in_hours=1,
            notification_email_address=email,
        )
        # Wait for training to complete
        start = time.time()
        while iteration.status != "Completed":
            iteration = self.trainer.get_iteration(self.project_id,
                                                   iteration.id)
            minutes, seconds = divmod(time.time() - start, 60)
            print(
                f"Training status: {iteration.status}",
                f"\t[{minutes:02.0f}m:{seconds:02.0f}s]",
                end="\r",
            )
            time.sleep(1)

        print()

        # The iteration is now trained. Publish it to the project endpoint
        iteration_name = uuid.uuid4()
        self.trainer.publish_iteration(
            self.project_id,
            iteration.id,
            iteration_name,
            self.prediction_resource_id,
        )
        with api.app.app_context():
            self.iteration_name = models.update_iteration_name(iteration_name)

    def delete_all_images(self) -> None:
        """
            Function for deleting uploaded images in Customv Vision.
        """
        try:
            self.trainer.delete_images(self.project_id,
                                       all_images=True,
                                       all_iterations=True)
        except Exception as e:
            raise Exception("Could not delete all images: " + str(e))

    def retrain(self):
        """
            Train model on all labels and update iteration.
        """
        with api.app.app_context():
            labels = models.get_all_labels()

        self.upload_images(labels, setup.CONTAINER_NAME_NEW)
        try:
            self.train(labels)
        except CustomVisionErrorException as e:
            msg = "No changes since last training"
            print(e, "exiting...")
            raise excp.BadRequest(msg)

    def hard_reset_retrain(self):
        """
            Train model on all labels and update iteration.
            This method sleeps for 60 seconds to make sure all
            old images are deleted from custom vision before
            uploading original dataset.
        """
        with api.app.app_context():
            labels = models.get_all_labels()

        # Wait 60 seconds to make sure all images are deleted in custom vision
        time.sleep(60)
        self.upload_images(labels, setup.CONTAINER_NAME_ORIGINAL)
        try:
            self.train(labels)
        except CustomVisionErrorException as e:
            msg = "No changes since last training"
            print(e, "exiting...")
            raise excp.BadRequest(msg)
 def dequeue_iterations(trainer: CustomVisionTrainingClient, custom_vision_project_id: str, max_iterations=2):
   """ Dequeue training iterations
   """
   iterations = trainer.get_iterations(custom_vision_project_id)
   if len(iterations) > max_iterations:
       trainer.delete_iteration(custom_vision_project_id, iterations[-1].as_dict()['id'])