Object Detection Using EfficientNet in Tensorflow 2
Rubens Zimbres, Ph.D.
ML Engineer, Gen AI, Sec+, Google Developer Expert in AI/ML ^ Google Cloud
In this tutorial, I'll show the necessary steps to create an object detection algorithm using Google Research's EfficientNet, in Tensorflow 2. The paper, EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks, is available here.
First, let's create the Anaconda environment:
conda create -n tf2 python=3.8 anaconda
source activate tf2
If source activate does not work, add the full path, like: /home/user/anaconda3/bin/activate tf2
Install Tensorflow:
pip install tensorflow-gpu
Now, go to your tf2 environment inside anaconda3 folder envs and find inside site-packages, where is tensorflow. It will be something like this:
cd /home/user/.conda/envs/tf2/lib/python3.8/site-packages/tensorflow
Now, inside tensorflow folder, git clone the tensorflow/models repository:
git clone https://github.com/tensorflow/models
Good, now, cd into the object detection folder:
cd models/research/object_detection
Now you must configure the object detection API and proto:
cd models/research
protoc object_detection/protos/*.proto --python_out=.
cp object_detection/packages/tf2/setup.py .
python -m pip install .
After that, create a folder inside the object_detection folder called "demo"
mkdir demo
cd demo
Now, inside demo folder you must create 5 other folders:
Now, let's do the annotation part. The images are located at /demo/images/train and test. You must first install labelImg from GitHub:
git clone https://github.com/tzutalin/labelImg
In Ubuntu:
sudo apt-get install pyqt5-dev-tool
sudo pip3 install -r requirements/requirements-linux-python3.txt
make qt5py3
python3 labelImg.py
Then you will type w and annotate (drag to a rectangle) the images with the format PascalVOC, which is a .xml file.
Now, inside the demo folder, add these 6 files from https://github.com/RubensZimbres/Repo-2022/tree/main/Object-Detection-Tensorflow2
Great. These are the steps:
Now it's the tricky part: you have to customize some files in order to succeed.
After applying the xml_to_csv.py file, you will get something like this for train and for test:
Now you must edit generate_tfrecord.py. For instance, if you have one class, change the following part of the code:
领英推荐
def class_text_to_int(row_label):
??? if row_label == 'desod':
??????? return 1
??? else:
??????? return None
For two classes:
def class_text_to_int(row_label):
??? if row_label == 'desod':
??????? return 1
??? if row_label == 'car':
??????? return 2
??? else:
??????? return None
Be sure you run these files inside the object_detection folder, as Python will need the utils package (a folder inside object_detection), otherwise you will get the "no module named utils" error. Another issue you may find is "no module named nets". In this case, run:
export PYTHONPATH=$PYTHONPATH=/home/theone/.conda/envs/tf2/lib/python3.8/site-packages/tensorflow/models/research:/home/theone/.conda/envs/tf2/lib/python3.8/site-packages/tensorflow/models/research/slim
Now let's generate the .record files:
python generate_tfrecord.py --csv_input=images/train_labels.csv --image_dir=images/train --output_path=train.record
python generate_tfrecord.py --csv_input=images/test_labels.csv --image_dir=images/test --output_path=test.record
Then, let's download the EfficientNet pre-trained weights:
wget https://download.tensorflow.org/models/object_detection/tf2/20200711/efficientdet_d0_coco17_tpu-32.tar.gz
tar -xvf efficientdet_d0_coco17_tpu-32.tar.gz
Extract this file to the folder Pre_Trained_Models. In side this folder, you will see there is a pipeline.config file. We are going to edit it, this is crucial. At the beggining of the file, chnage to the number of classes you want:
model
? ssd {
??? num_classes: 1
??? image_resizer {
????? keep_aspect_ratio_resizer {
??????? min_dimension: 512
??????? max_dimension: 512
??????? pad_to_max_dimension: true
????? }
Then, at train config part, adjust the batch size to some value that fits in the memory of your computer:
train_config
? batch_size: 4
? data_augmentation_options {
??? random_horizontal_flip {
??? }
? }
? data_augmentation_options {
??? random_scale_crop_and_pad_to_square {
????? output_size: 512
????? scale_min: 0.10000000149011612
????? scale_max: 2.0
??? }
? }
Then, fill 5 more paths: fine_tune checkpoint to where is the EfficientNet checkpoints, 2 label_map_path to where is your labelmap.pbtxt file (inside Annotations folder) and the path to your train and test.record files (inside Annotations folder). Two more setups:
Fix the number of steps to 5000 and fine_tune_checkpoint_type to "detection". If you keep the fine_tune_checkpoint_type as "classification" the output will be a class (number), but we need a dictionary with the annotated boxes of object detection. This part will look like this:
? fine_tune_checkpoint: "/home/theone/.conda/envs/tf2/lib/python3.8/site-packages/tensorflow/models/research/object_detection/training-demo-tf2/pre-trained-models/efficientdet_d0_coco17_tpu-32/checkpoint/ckpt-0
? num_steps: 5000
? startup_delay_steps: 0.0
? replicas_to_aggreg.ate: 4
? max_number_o_boxes: 100
? unpad_groundtruth_tensors: false
? fine_tune_checkpoint_type: "detection"
? use_bfloat16: true
? fine_tune_checkpoint_version: V2"
Now, one last setup: in the folder Annotations, edit label_map.pbtxt to contain this (adjust to the number of classes you have):
item {
? id: 1
? name: 'desod'
}
Now we can train the object detection model (inside /object_detection folder) using the model_main_tf2.py file. Remember, the output folder inside demo folder must be empty in order to avoid errors.
python model_main_tf2.py --pipeline_config_path=./training-demo-tf2/pre-trained-models/efficientdet_d0_coco17_tpu-32/pipeline.config --model_dir=./training-demo-tf2/output --alsologtostderr
Good, now we can export the inference_graph. Still inside the /object_detection folder:
python exporter_main_v2.py --trained_checkpoint_dir=./training-demo-tf2/output --pipeline_config_path=./training-demo-tf2/pre-trained-models/efficientdet_d0_coco17_tpu-32/pipeline.config --output_directory ./training-demo-tf2/inference_graph
This will generate a .pb file whose path must be added to the command line of python3 webcam.py file for inference, along with the labelmap.pbtxt path. Be sure to install OpenCV:
pip3 install opencv-python
Now, if you want, you can deploy the model in the cloud. Add the Python inference file containing the flask app, requirements.txt (libraries required), .yaml files (configurations) and Dockerfile to a folder. The idea is to generate an image in Google Cloud Container Registry and deploy to Cloud Run for inference.
Supposing you are in the folder where the files (requirements.txt, .yaml files) and Dockerfile are, you can create a docker image:
gcloud builds submit --tag gcr.io/your_project_id/image_name .
Then deploy in Cloud Run:
gcloud run deploy --image gcr.io/your_project_id/image_name
For GKE (Google Kubernetes Engine):
$ gcloud container clusters create example-gke --num-nodes 1 --enable-basic-auth --issue-client-certificate --enable-autoscaling --min-nodes 1 --max-nodes 3 --region us-central1 --machine-type n1-standard-2 --local-ssd-count 1 --scopes=cloud-platform,storage-full,compute-rw,service-control,cloud-source-repos --service-account [email protected]
$ gcloud container clusters get-credentials example-gke --region=us-central1
$ kubectl create secret generic my-app-sa-key --from-file service-account.json
$ kubectl get secret
$ kubectl apply -f deployment.yaml
$ kubectl get pods
$ kubectl get service
$ kubectl describe pod example-gke-12345
$ kubectl apply -f allow-all-network-policy.yaml
$ kubectl apply -f service.yaml
Hey! I want to implement EfficientNet on image dataset to classify normal signal or abnormal. The problem is I want 32x32(smaller the better) and gray scale only because later on I will be moving for hardware so yeah. I'm trying to use transfer learning. Do you think there is anyway to do that?
Solutions Architect at Thomson Reuters
2 年Thanks Rubens. Helpful.