home/exp1000/acquire_and_label_images.py
def cluster_labeled_images(self, cluster_for_labels, k, training_data_size_threshold, image_types_to_cluster):
        """Train or apply K-Means clustering to subclassify images that have already been classifed byt the TensorFlow Lite classification pipeline."""

        for label in cluster_for_labels:
            # Build the path to the labeled images that we want to cluster/sub-classify.
            toGround_label_dir = TOGROUND_PATH + '/' + label
            
            # Only cluster/sub-classify the labeled images of thumbnail images exist for that label group.
            # If a clustering model has not been trained yet the start collecting training data or train the model if we have collected enough data from previous runs.
            if os.path.exists(toGround_label_dir):

                # Build the file path of the label's cluster centroids CSV file.
                centroids_file_path = KMEANS_CENTROIDS_DIR_PATH + '/' + label + '.csv'

                # Check if K-Means centroids CSV file exists.
                # A centroids CSV file can be thought as a the serialized output of the trained model.
                if os.path.exists(centroids_file_path):
                    # The label in question has a centroids CSV file associated to it.
                    # The centroids CSV file can be used to cluster the thumbnail images.

                    # The command string to cluster the images using K-Means.
                    cmd = "{BIN} {M} {IMG_DIR} {IMG_TRAIN_TYPE} {CLUSTER_DIR} {IMG_CLUSTER_TYPE} {C}".format(
                        BIN=KMEANS_BIN_PATH,
                        M=KMEANS_BIN_MODE_BATCH_PREDICT,
                        IMG_DIR=toGround_label_dir,
                        IMG_TRAIN_TYPE=KMEANS_IMG_TRAIN_TYPE,
                        CLUSTER_DIR=toGround_label_dir,
                        IMG_CLUSTER_TYPE=",".join(image_types_to_cluster),
                        C=centroids_file_path)

                    # Log the clustering command that will be executed.
                    logger.info('Executing K-Means command: {CMD}'.format(CMD=cmd))

                    # Create a subprocess to execute the K-Means program.
                    process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)

                    # Get program stdout and stderr.
                    std_out, std_err = process.communicate()

                    # Get program error code.
                    return_code = process.returncode

                    # If program ran without errors then just log success.
                    if return_code == 0:
                        # Log summary of what happened.
                        logger.info("Successfully used K-Means clustering to subclassify labeled images.")
                    
                    else: 
                        # Log error code and message if the K-Means program returned and error code.
                        logger.error("K-Means clustering returned error code {E}. {M}".format(E=return_code, M=std_err.decode("utf-8")))

                else:
                    # If the centroids CSV file doesn't exist then it means that the clustering model has not been trained yet.
                    # Check if we collected enough training data to train the clustering model.
                    # If we haven't collected enough training data then keep collecting training data.
                    # A single training data input is simply the grayscaled pixel values of a downsampled thumbnail image that is used to train the model.
                    # The training data CSV file are rows of training image inputs with each row being a collection of the grayscaled pixel values for an training image.

                    # Build the file path to the CSV file where all training data is persisted.
                    training_data_file = KMEANS_TRAINING_DATA_DIR_PATH + '/' + label + '.csv'

                    # If the training data CSV file exist then we either have to keep collecting data (appending new training data rows to the file)
                    # or use all the thus far collected training data to train a K-Means clustering model.
                    # Which approach we take depends on the training data size threshold set in the app's config file.
                    if os.path.exists(training_data_file):

                        # Count the number of training inputs collected thus far in the training data CSV file.
                        training_data_size = sum(1 for line in open(training_data_file))

                        # Not enough training data has been collected yet. Keep collecting training data.
                        # Invoke the appropriate K-Means executable binary command and make sure this Python app waits for the program to be completed before
                        # continuing. This is because the training data that we are collecting are the thumbnail image files that are currently in the app's
                        # toGround folder and these images will be removed during the thumbnail tarring phase of the SmartCam app.
                        if training_data_size < training_data_size_threshold:
                            
                            # The command string to collect training data.
                            cmd = '{BIN} {M} {IMG_DIR} {IMG_TRAIN_TYPE} {T}'.format(
                                BIN=KMEANS_BIN_PATH,
                                M=KMEANS_BIN_MODE_COLLECT,
                                IMG_DIR=toGround_label_dir,
                                IMG_TRAIN_TYPE=KMEANS_IMG_TRAIN_TYPE,
                                T=training_data_file)

                            # Log the training command that will be executed.
                            logger.info('Executing K-Means command: {CMD}'.format(CMD=cmd))

                            # Create a subprocess to execute the K-Means program.
                            process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)

                            # Get program stdout and stderr.
                            std_out, std_err = process.communicate()

                            # Get program error code.
                            return_code = process.returncode

                            # If program ran without errors then just log success.
                            if return_code == 0:
                                # Log summary of what happened.
                                logger.info("Appended {C} training data inputs into {T}.".format(C=std_out.decode("utf-8"), T=training_data_file))
                            
                            else: 
                                # Log error code and message if the K-Means program returned and error code.
                                logger.error("K-Means training data collection returned error code {E}. {M}".format(E=return_code, M=std_err.decode("utf-8")))

                        else:
                            # We can proceed with training the clustering model if enough training data has been collected since the last time the app was executed.
                            # The trained model will be serialized as a centroids CSV file for the current label group.
                            # However, we won't proceed with clustering the current batch of images because training will happen in the backround (fire and forget)
                            # so we want to wait until the next run of the SmartCam app to check if the centroids file was successfully created or not.
                            
                            # The training command string.
                            cmd = '{BIN} {M} {K} {T} {C}'.format(
                                BIN=KMEANS_BIN_PATH,
                                M=KMEANS_BIN_MODE_TRAIN,
                                K=k,
                                T=training_data_file, 
                                C=centroids_file_path)
                            
                            # Log the training command that will be executed.
                            logger.info('Executing K-Means command: {CMD}'.format(CMD=cmd))

                            # Execute the training command. Invoke the K-Means executable binary without blocking this Python app (fire and forget).
                            # Make sure that hte K-Means executable binary is spawed as a separate process so that it still runs even if the parent process that 
                            # spawed it is killed. Training might take a bit of time to complete so we want to prevent it from blocking the SmarCam's execution.
                            # We want the training to happen and complete in the background even after the SmartCam app has finished running.
                            subprocess.Popen(cmd, preexec_fn=os.setsid, shell=True)

                    else:
                        # Training data CSV file does not exist.
                        # Start collecting training data now.

                        # The command string to collect training data.
                        cmd = '{BIN} {M} {IMG_DIR} {IMG_TRAIN_TYPE} {T}'.format(
                            BIN=KMEANS_BIN_PATH,
                            M=KMEANS_BIN_MODE_COLLECT,
                            IMG_DIR=toGround_label_dir,
                            IMG_TRAIN_TYPE=KMEANS_IMG_TRAIN_TYPE,
                            T=training_data_file)

                        # Log the training command that will be executed.
                        logger.info('Executing K-Means command: {CMD}'.format(CMD=cmd))

                        # Create a subprocess to execute the K-Means program.
                        process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)

                        # Get program stdout and stderr.
                        std_out, std_err = process.communicate()

                        # Get program error code.
                        return_code = process.returncode

                        # If program ran without errors then just log success.
                        if return_code == 0:
                            # Log summary of what happened.
                            logger.info("Initialized training data file with {C} inputs into {T}.".format(C=std_out.decode("utf-8"), T=training_data_file))
                        
                        else: 
                            # Log error code and message if the K-Means program returned and error code.
                            logger.error("K-Means training data collection returned error code {E}. {M}".format(E=return_code, M=std_err.decode("utf-8")))
Train or apply K-Means clustering to subclassify images that have already been classifed byt the TensorFlow Lite classification pipeline.
Train or apply K-Means clustering to subclassify images that have already been classifed byt the TensorFlow Lite classification pipeline.
Train or apply K - Means clustering to subclassify images that have already been classifed byt the TensorFlow Lite classification pipeline .
def cluster_labeled_images(self, cluster_for_labels, k, training_data_size_threshold, image_types_to_cluster):
        for label in cluster_for_labels:
            toGround_label_dir = TOGROUND_PATH + '/' + label
            if os.path.exists(toGround_label_dir):
                centroids_file_path = KMEANS_CENTROIDS_DIR_PATH + '/' + label + '.csv'
                if os.path.exists(centroids_file_path):
                    cmd = "{BIN} {M} {IMG_DIR} {IMG_TRAIN_TYPE} {CLUSTER_DIR} {IMG_CLUSTER_TYPE} {C}".format(
                        BIN=KMEANS_BIN_PATH,
                        M=KMEANS_BIN_MODE_BATCH_PREDICT,
                        IMG_DIR=toGround_label_dir,
                        IMG_TRAIN_TYPE=KMEANS_IMG_TRAIN_TYPE,
                        CLUSTER_DIR=toGround_label_dir,
                        IMG_CLUSTER_TYPE=",".join(image_types_to_cluster),
                        C=centroids_file_path)
                    logger.info('Executing K-Means command: {CMD}'.format(CMD=cmd))
                    process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
                    std_out, std_err = process.communicate()
                    return_code = process.returncode
                    if return_code == 0:
                        logger.info("Successfully used K-Means clustering to subclassify labeled images.")
                    else: 
                        logger.error("K-Means clustering returned error code {E}. {M}".format(E=return_code, M=std_err.decode("utf-8")))
                else:
                    training_data_file = KMEANS_TRAINING_DATA_DIR_PATH + '/' + label + '.csv'
                    if os.path.exists(training_data_file):
                        training_data_size = sum(1 for line in open(training_data_file))
                        if training_data_size < training_data_size_threshold:
                            cmd = '{BIN} {M} {IMG_DIR} {IMG_TRAIN_TYPE} {T}'.format(
                                BIN=KMEANS_BIN_PATH,
                                M=KMEANS_BIN_MODE_COLLECT,
                                IMG_DIR=toGround_label_dir,
                                IMG_TRAIN_TYPE=KMEANS_IMG_TRAIN_TYPE,
                                T=training_data_file)
                            logger.info('Executing K-Means command: {CMD}'.format(CMD=cmd))
                            process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
                            std_out, std_err = process.communicate()
                            return_code = process.returncode
                            if return_code == 0:
                                logger.info("Appended {C} training data inputs into {T}.".format(C=std_out.decode("utf-8"), T=training_data_file))
                            else: 
                                logger.error("K-Means training data collection returned error code {E}. {M}".format(E=return_code, M=std_err.decode("utf-8")))
                        else:
                            cmd = '{BIN} {M} {K} {T} {C}'.format(
                                BIN=KMEANS_BIN_PATH,
                                M=KMEANS_BIN_MODE_TRAIN,
                                K=k,
                                T=training_data_file, 
                                C=centroids_file_path)
                            logger.info('Executing K-Means command: {CMD}'.format(CMD=cmd))
                            subprocess.Popen(cmd, preexec_fn=os.setsid, shell=True)
                    else:
                        cmd = '{BIN} {M} {IMG_DIR} {IMG_TRAIN_TYPE} {T}'.format(
                            BIN=KMEANS_BIN_PATH,
                            M=KMEANS_BIN_MODE_COLLECT,
                            IMG_DIR=toGround_label_dir,
                            IMG_TRAIN_TYPE=KMEANS_IMG_TRAIN_TYPE,
                            T=training_data_file)
                        logger.info('Executing K-Means command: {CMD}'.format(CMD=cmd))
                        process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
                        std_out, std_err = process.communicate()
                        return_code = process.returncode
                        if return_code == 0:
                            logger.info("Initialized training data file with {C} inputs into {T}.".format(C=std_out.decode("utf-8"), T=training_data_file))
                        else: 
                            logger.error("K-Means training data collection returned error code {E}. {M}".format(E=return_code, M=std_err.decode("utf-8")))
def cluster_labeled_images ( self , cluster_for_labels , k , training_data_size_threshold , image_types_to_cluster ) : for label in cluster_for_labels : toGround_label_dir = TOGROUND_PATH + '/' + label if os . path . exists ( toGround_label_dir ) : centroids_file_path = KMEANS_CENTROIDS_DIR_PATH + '/' + label + '.csv' if os . path . exists ( centroids_file_path ) : cmd = "{BIN} {M} {IMG_DIR} {IMG_TRAIN_TYPE} {CLUSTER_DIR} {IMG_CLUSTER_TYPE} {C}" . format ( BIN = KMEANS_BIN_PATH , M = KMEANS_BIN_MODE_BATCH_PREDICT , IMG_DIR = toGround_label_dir , IMG_TRAIN_TYPE = KMEANS_IMG_TRAIN_TYPE , CLUSTER_DIR = toGround_label_dir , IMG_CLUSTER_TYPE = "," . join ( image_types_to_cluster ) , C = centroids_file_path ) logger . info ( 'Executing K-Means command: {CMD}' . format ( CMD = cmd ) ) process = subprocess . Popen ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE , shell = True ) std_out , std_err = process . communicate ( ) return_code = process . returncode if return_code == 0 : logger . info ( "Successfully used K-Means clustering to subclassify labeled images." ) else : logger . error ( "K-Means clustering returned error code {E}. {M}" . format ( E = return_code , M = std_err . decode ( "utf-8" ) ) ) else : training_data_file = KMEANS_TRAINING_DATA_DIR_PATH + '/' + label + '.csv' if os . path . exists ( training_data_file ) : training_data_size = sum ( 1 for line in open ( training_data_file ) ) if training_data_size < training_data_size_threshold : cmd = '{BIN} {M} {IMG_DIR} {IMG_TRAIN_TYPE} {T}' . format ( BIN = KMEANS_BIN_PATH , M = KMEANS_BIN_MODE_COLLECT , IMG_DIR = toGround_label_dir , IMG_TRAIN_TYPE = KMEANS_IMG_TRAIN_TYPE , T = training_data_file ) logger . info ( 'Executing K-Means command: {CMD}' . format ( CMD = cmd ) ) process = subprocess . Popen ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE , shell = True ) std_out , std_err = process . communicate ( ) return_code = process . returncode if return_code == 0 : logger . info ( "Appended {C} training data inputs into {T}." . format ( C = std_out . decode ( "utf-8" ) , T = training_data_file ) ) else : logger . error ( "K-Means training data collection returned error code {E}. {M}" . format ( E = return_code , M = std_err . decode ( "utf-8" ) ) ) else : cmd = '{BIN} {M} {K} {T} {C}' . format ( BIN = KMEANS_BIN_PATH , M = KMEANS_BIN_MODE_TRAIN , K = k , T = training_data_file , C = centroids_file_path ) logger . info ( 'Executing K-Means command: {CMD}' . format ( CMD = cmd ) ) subprocess . Popen ( cmd , preexec_fn = os . setsid , shell = True ) else : cmd = '{BIN} {M} {IMG_DIR} {IMG_TRAIN_TYPE} {T}' . format ( BIN = KMEANS_BIN_PATH , M = KMEANS_BIN_MODE_COLLECT , IMG_DIR = toGround_label_dir , IMG_TRAIN_TYPE = KMEANS_IMG_TRAIN_TYPE , T = training_data_file ) logger . info ( 'Executing K-Means command: {CMD}' . format ( CMD = cmd ) ) process = subprocess . Popen ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE , shell = True ) std_out , std_err = process . communicate ( ) return_code = process . returncode if return_code == 0 : logger . info ( "Initialized training data file with {C} inputs into {T}." . format ( C = std_out . decode ( "utf-8" ) , T = training_data_file ) ) else : logger . error ( "K-Means training data collection returned error code {E}. {M}" . format ( E = return_code , M = std_err . decode ( "utf-8" ) ) )
Train or apply K-Means clustering to subclassify images that have already been classifed byt the TensorFlow Lite classification pipeline.
Train or apply K - Means clustering to subclassify images that have already been classifed byt the TensorFlow Lite classification pipeline .
"""Train or apply K-Means clustering to subclassify images that have already been classifed byt the TensorFlow Lite classification pipeline.""" # Build the path to the labeled images that we want to cluster/sub-classify. # Only cluster/sub-classify the labeled images of thumbnail images exist for that label group. # If a clustering model has not been trained yet the start collecting training data or train the model if we have collected enough data from previous runs. # Build the file path of the label's cluster centroids CSV file. # Check if K-Means centroids CSV file exists. # A centroids CSV file can be thought as a the serialized output of the trained model. # The label in question has a centroids CSV file associated to it. # The centroids CSV file can be used to cluster the thumbnail images. # The command string to cluster the images using K-Means. # Log the clustering command that will be executed. # Create a subprocess to execute the K-Means program. # Get program stdout and stderr. # Get program error code. # If program ran without errors then just log success. # Log summary of what happened. # Log error code and message if the K-Means program returned and error code. # If the centroids CSV file doesn't exist then it means that the clustering model has not been trained yet. # Check if we collected enough training data to train the clustering model. # If we haven't collected enough training data then keep collecting training data. # A single training data input is simply the grayscaled pixel values of a downsampled thumbnail image that is used to train the model. # The training data CSV file are rows of training image inputs with each row being a collection of the grayscaled pixel values for an training image. # Build the file path to the CSV file where all training data is persisted. # If the training data CSV file exist then we either have to keep collecting data (appending new training data rows to the file) # or use all the thus far collected training data to train a K-Means clustering model. # Which approach we take depends on the training data size threshold set in the app's config file. # Count the number of training inputs collected thus far in the training data CSV file. # Not enough training data has been collected yet. Keep collecting training data. # Invoke the appropriate K-Means executable binary command and make sure this Python app waits for the program to be completed before # continuing. This is because the training data that we are collecting are the thumbnail image files that are currently in the app's # toGround folder and these images will be removed during the thumbnail tarring phase of the SmartCam app. # The command string to collect training data. # Log the training command that will be executed. # Create a subprocess to execute the K-Means program. # Get program stdout and stderr. # Get program error code. # If program ran without errors then just log success. # Log summary of what happened. # Log error code and message if the K-Means program returned and error code. # We can proceed with training the clustering model if enough training data has been collected since the last time the app was executed. # The trained model will be serialized as a centroids CSV file for the current label group. # However, we won't proceed with clustering the current batch of images because training will happen in the backround (fire and forget) # so we want to wait until the next run of the SmartCam app to check if the centroids file was successfully created or not. # The training command string. # Log the training command that will be executed. # Execute the training command. Invoke the K-Means executable binary without blocking this Python app (fire and forget). # Make sure that hte K-Means executable binary is spawed as a separate process so that it still runs even if the parent process that  # spawed it is killed. Training might take a bit of time to complete so we want to prevent it from blocking the SmarCam's execution. # We want the training to happen and complete in the background even after the SmartCam app has finished running. # Training data CSV file does not exist. # Start collecting training data now. # The command string to collect training data. # Log the training command that will be executed. # Create a subprocess to execute the K-Means program. # Get program stdout and stderr. # Get program error code. # If program ran without errors then just log success. # Log summary of what happened. # Log error code and message if the K-Means program returned and error code.
self
cluster_for_labels
k
training_data_size_threshold
image_types_to_cluster