The paths in this lesson don't use the Google Drive, however, if you do want to use the Google Drive, you can replace birds
with drive/My Drive/birds
.
Note that content stored in data
will be deleted whenever you close the notebook.
from google.colab import drive
drive.mount('/content/drive')
Creating your own dataset from Google Images
by: Francisco Ingham and Jeremy Howard. Inspired by Adrian Rosebrock
In this tutorial we will see how to easily create an image dataset through Google Images.
First let's install the new library again (if you do not have it already)
And import our libraries
from fastai.vision.all import *
Below you will find the exact imports for everything we use today
from fastcore.foundation import L
from fastcore.xtras import Path # @patch'd properties to the Pathlib module
from fastai.callback.fp16 import to_fp16
from fastai.callback.schedule import fit_one_cycle, lr_find
from fastai.data.block import CategoryBlock, DataBlock
from fastai.data.transforms import get_image_files, Normalize, RandomSplitter, parent_label
from fastai.interpret import ClassificationInterpretation
from fastai.learner import Learner # imports @patch'd properties to Learner including `save`, `load`, `freeze`, and `unfreeze`
from fastai.vision.augment import aug_transforms, RandomResizedCrop
from fastai.vision.core import imagenet_stats
from fastai.vision.data import ImageBlock
from fastai.vision.learner import cnn_learner
from fastai.vision.utils import download_images, verify_images
Go to Google Images and search for the images you are interested in. The more specific you are in your Google Search, the better the results and the less manual pruning you will have to do.
Scroll down until you've seen all the images you want to download, or until you see a button that says 'Show more results'. All the images you scrolled past are now available to download. To get more, click on the button, and continue scrolling. The maximum number of images Google Images shows is 700.
It is a good idea to put things you want to exclude into the search query, for instance if you are searching for the Eurasian wolf, "canis lupus lupus", it might be a good idea to exclude other variants:
"canis lupus lupus" -dog -arctos -familiaris -baileyi -occidentalis
You can also limit your results to show only photos by clicking on Tools and selecting Photos from the Type dropdown.
Now you must run some Javascript code in firefox which will save the URLs of all the images you want for you dataset.
Press CtrlShiftK in Windows/Linux and CmdOptJ in Mac, and a small window the javascript 'Console' will appear. That is where you will paste the JavaScript commands.
You will need to get the urls of each of the images. You can do this by running the following commands:
urls = Array.from(document.querySelectorAll('.rg_di .rg_meta')).map(el=>JSON.parse(el.textContent).ou);
window.open('data:text/csv;charset=utf-8,' + escape(urls.join('\n')));
Do this one at a time as you'll want to rename your files to SomeFileName.txt
(with SomeFileName being replaced)
Choose an appropriate name for your labeled images.
folders = ['blue_bird', 'red_wing_black_bird', 'blue_jay']
files = ['urls_blue.txt', 'urls_rwbb.txt', 'urls_jay.txt']
Now let's make a folder for each category
Now, upload your urls files. You just need to press 'Upload' in your working directory (birds
), select your url files and confirm the upload.
classes = ['blue_bird', 'red_wing_black_bird','blue_jay']
path = Path('birds')
path.mkdir(parents=True, exist_ok=True)
Let's download our images
for i, n in enumerate(classes):
print(n)
path_f = Path(files[i])
download_images(path/n, path_f, max_pics=50)
And check they are all good. If not, we will delete them
imgs = L()
for n in classes:
print(n)
path_n = path/n
imgs += verify_images(path_n.ls())
imgs
for im in imgs:
im.unlink()
Let's double check
imgs = L()
for n in classes:
print(n)
path_n = path/n
imgs += verify_images(path_n.ls())
imgs
View data
Let's make our DataBlock
again.
birds = DataBlock(blocks=(ImageBlock, CategoryBlock),
get_items=get_image_files,
splitter=RandomSplitter(0.2),
get_y=parent_label,
item_tfms=RandomResizedCrop(460),
batch_tfms=[*aug_transforms(size=224, max_warp=0), Normalize.from_stats(*imagenet_stats)])
dls = birds.dataloaders(path, bs=32)
Good! Let's take a look at some of our pictures then.
dls.show_batch(max_n=9)
dls.vocab
learn = cnn_learner(dls, resnet34, pretrained=True, metrics=error_rate).to_fp16()
learn.fit_one_cycle(4)
learn.save('stage-1')
learn.unfreeze()
learn.lr_find()
learn.fit_one_cycle(2, lr_max=slice(1e-4, 1e-3))
learn.save('stage-2')
learn.load('stage-2');
interp = ClassificationInterpretation.from_learner(learn)
interp.plot_confusion_matrix()
interp.plot_top_losses(3, figsize=(9,9))