Copying multiple Custom Vision projects between Cognitive Services resources may cause problems, and it's not one of the most pleasant things to do. In this short post we will find out how to accelerate this procedure.
Have you ever needed to migrate to a new Azure subscription, a new tenant or just to copy a Custom Vision project in the same account? Creating each project, copying all images manually and going through the whole tagging procedure once again sounds really cumbersome. Fortunately, Custom Vision APIs are rich enough and this procedure can be easily done programmatically. There are two provided APIs, Prediction and Training. We will use the second one, which allows us to completely manage a whole project. By using the training API you can create a new project, upload images, create tags, pin tags to image regions, train or publish your model and, finally, quickly test images within your model. All operations are listed in the training API reference.
In addition to the REST API, Custom Vision also comes with SDKs for several programming languages - C#, Java,
easier, Azure provides a set of code samples that showcase a variety of tools, and
accompanying tutorials. Among them you will find a
Python script sample which migrates the desirable project
between two Cognitive Services resources. As mentioned above, there are two Custom Vision APIs and several SDKs. For the
purpose of this blog, we will use the
and more specifically the
CustomVisionTrainingClient class which contains all operations related to project
management, tagging and training.
Before running the script, ensure that there are no duplicate images in your project that you wish to copy, otherwise,
the execution of it will fail by setting
in_batch_successful variable from
Also, don't try to use the
move task in the Azure portal in order to transfer manually the whole Cognitive Services
resource between resource groups. This operation won't work with Custom Vision projects attached to them. The moving
procedure will finish successfully, but the attached projects will be bugged and unusable.
The Python script sample is divided into three main functions:
migrate_project- Creates the destination project based on the given source project.
migrate_tags- Migrates all tags from the source project to destination project.
migrate_images- Migrates of all tagged and untagged images.
However, it has one limitation. It can only migrate a single project from a source to destination endpoint. Let's extend
a bit the main function and make it able to re-create and migrate all the Custom Vision projects to pointed destination
CustomVisionTrainingClient class contains one more operation that we can use for this purpose. We will
use a method called
get_projects which returns a list of objects of type
Project. Then we can just iterate over this
list, retrieve id of each project and finally call those three main functions as we would do for a single project.
for project in src_trainer.get_projects(): logging.info("Collecting information for source project:", project.id) destination_project = migrate_project(src_trainer, dest_trainer, project.id) (1) tags = migrate_tags(src_trainer, dest_trainer, project.id, destination_project.id) (2) source_images = migrate_images(src_trainer, dest_trainer, project.id, destination_project.id, tags)
src_trainer- The CustomVisionTrainingClient object of the source projects. Created in https://github.com/Azure-Samples/custom-vision-move-project/blob/master/migrate_project.py#L111.
dest_trainer- The CustomVisionTrainingClient object of the destination projects. Created in https://github.com/Azure-Samples/custom-vision-move-project/blob/master/migrate_project.py#L114.
The client contains all the methods which correspond to the operations from the Training API.
We should also remove the
arg_parser line with the
project_id argument as it refers to a single project. It won't be
longer necessary for us.
arg_parser.add_argument("-p", "--project", action="store", type=str, help="Source project ID", dest="project_id", default=None)
...and it's done. By doing those small changes, we are now able to migrate all projects between two Custom Vision accounts. The migration script should properly re-create all settings (like domain settings) in all the destination projects. Sadly, newly created projects are untrained and unpublished so our script needs some more customization or manual work. This should not be a big problem as training is a one-click operation in the web app. If you are a stubborn and headstrong person (like me), and you want to fully automate this procedure, you can try something like this:
for project in src_trainer.get_projects(): logging.info("Collecting information for source project:", project.id) destination_project = migrate_project(src_trainer, dest_trainer, project.id) tags = migrate_tags(src_trainer, dest_trainer, project.id, destination_project.id) source_images = migrate_images(src_trainer, dest_trainer, project.id, destination_project.id, tags) dest_trainer.train_project(destination_project.id, "Regular") while dest_trainer.get_iterations(destination_project.id).status == "Training": if dest_trainer.get_iterations(destination_project.id).status == "Completed": logging.info("Training completed: ", destination_project.id) iteration_id = dest_trainer.get_iterations(destination_project.id).id dest_trainer.publish_iteration(destination_project.id, iteration_id, destination_project.name, destination_resource_id) (1) break else: logging.info("Training in progress: ", destination_project.id) time.sleep(60)
destination_resource_id- the id of the Cognitive Services account which Custom Vision is connected with. The value can be found in settings of the destination account. Pay attention to this value as it points the Cognitive Services resource which will be associated with each project. You might have multiple Cognitive Services resources in your subscription (e.g. for each environment). In this case you should try to assign this value differently. The variable should look like this:
This code snippet could be written better and more elaborately but let's not focus too much on details. After successful
training of all projects, if needed, set your desired probability and overlap threshold values. They are not
automatically updated during migration. As you can also see, we trained the project using "
It's the equivalent of "Quick Training" in the web platform. If you want to perform the advanced training, you should
trainingType. When using
Advanced, do not forget to set your desired training budget in hours in
order to optimize your training costs -
reservedBudgetInHours parameter. By default, this value is set to
We successfully went through the migration process of multiple Custom Vision projects. The described approach could be modified and customized according to your needs. In this post I only wanted to give you an idea of how this thing could be done and point out the problems that you may encounter. I hope that you liked it and you will find some of this information useful.
Hero image by bantersnaps, opens in a new window