Bom dia, boa tarde, boa noite!
Essa é a sétima parte da série sobre o projeto Video Creator, onde mostrarei como fiz a busca pelas imagens.
Se você entrou direto nesse post, te aconselho a começar por aqui, para entender exatamente do que se trata essa série.
Sobre essa parte
Basicamente o que fiz foi concatenar o assunto pesquisado com a primeira keyword da lista de keywords de cada sentença.
Bem simples!
Requisitos:
O principal requisito, é claro, é óbvio… criação do Bing Resource na Azure e a criação da instância do Bing Custom Search. Tudo isso eu mostrei no último post!
Utilizei também 2 imports praticamente pradrões nesse projeto:
import json
import requests
rimage.py
A parte da busca e do download das imagens, ficou no robô rimage.py.
A chamada ao endpoint do ping resolvi colocar dentro de uma função que recebe 2 parâmetros: a query de pesquisa e a quantidade de imagens que o serviço irá devolver. Ficou assim:
# implementando busca de imagens pelo Bing
def search_images_on_bing(query, count="1"):
logging.info("Searching images on Bing with custom bing image search")
url = credentials['bing_endpoint'] + "?q=" + query + "&count="+ count +"&customconfig=" + credentials['bing_custom_config_id'] +"&licence=ShareCommercially&size=Large"
r = requests.get(url, headers={'Ocp-Apim-Subscription-Key': credentials['azure_subscription_key']})
response = json.loads(r.text)
if 'value' in response:
result = [d['contentUrl'] for d in response['value']]
else:
result = []
return result
Notem que essa função é bem simples, recebe uma query e a quantidade que ela deve retornar de resultado, ai foi só bater na api passando esses parâmetros, fazer o parser do json e extrair somente os links das imagens para enviar como retorno.
Para esse projeto eu utilizei os seguintes parâmetros:
- licence=ShareCommercially
- Retornará imagens que podem ser usadas com propósito pessoal ou comercial
- size=Large
- Retornará imagens de no mínimo 500×500 pixels
A Api do bing é realmente fantástica. Existem inúmeros parâmetros que podem ser usados para refinar a busca. Quem quiser personalizar ainda mais a busca, só ver os parametros disponíveis na página oficial da api:
Criei uma outra função responsável por iterar nas sentenças, montar a query de pesquisa e chamar a função acima. Ficou assim:
def fetch_images_from_sentences():
logging.info("Fetching images from sentences...")
print("Fetching images from sentences", end='\n\n')
# loading content
logging.info("Get sentences from object saved")
print("Loading content from content.json")
video_content = rcontent.load()
for sentence in video_content['sentences']:
if len(sentence['keywords'])>0:
if video_content['search_term'] != sentence['keywords'][0]:
sentence['image_search_query'] = "{} {}".format(video_content['search_term'], sentence['keywords'][0])
sentence['images'] = search_images_on_bing(sentence['image_search_query'], "5")
time.sleep(1.5)
rcontent.save(video_content)
Três pontos importantes aqui:
O primeiro é sobre o atributo sentence['image_search_query']
, onde eu armazeno o termo que eu utilizei para buscar as imagens, e ele é composto pelo assunto do video + a primeira keyword da lista. Isso para evitar que seja buscado imagens com uma keyword muito genérica que não tenha ligação com o assunto principal.
O segundo é sobre como foi construído o fluxo das coisas. O robô de imagem funciona completamente independente dos demais. O que ele precisa é que exista um arquivo content.json na estrutura esperada. Por isso quando rodamos o rimage.py, ele utiliza a função load() do rcontent.py para buscar o conteúdo do video e efetuar a busca das imagens. Após encontrar as imagens, ele gera uma lista com os links e grava dentro do atributo images, dentro de sentences.
O terceiro ponto é o time.sleep(1.5)
no final da função, que precisei incluir para respeitar os limites de Free Tier do Bing Resource. Com isso, eu garanto que só vou fazer 1 chamada por segundo.
Download das imagens
Para o download das imagens, inclui todos os passos dentro de uma função que eu chamei de download_images()
. Ficou assim:
def download_images():
logging.info("Downloading images from each sentences")
#os.chdir('./')
path = CONTENT_IMAGES_PATH
# create directory
os.makedirs(path, exist_ok=True)
# limpando a pasta
os.system("rm -rf {}/*".format(path))
video_content = rcontent.load()
list_img = []
for idx_s, sentence in enumerate(video_content['sentences']):
for idx_i, image in enumerate(sentence['images']):
if image not in list_img:
# if an image doesn't downloaded, try another one
try:
print("Trying to download: ", image)
image_filename = "{}/{}_original.jpg".format(path,idx_s)
wget.download(image,image_filename)
list_img.append(image)
print("")
break
except Exception as ex:
logging.error(ex)
continue
video_content['images_used'] = list_img
rcontent.save(video_content)
O que essa função faz é basicamente:
- verificar se a pasta onde ficará as imagens já existe, se não… cria…
- Remover todas as imagens existentes na pasta
- Carrega o conteúdo da content.json para buscar os links das imagens buscadas
- Itera nas sentenças e nas imagens encontradas.
- Faz uma verificação se a imagem já não foi baixada
- Tenta realizar o download da imagem, se por algum motivo ele não conseguir, ele tenta a próxima imagem.
- Grava o link das imagens baixadas dentro do atributo images_used e salva o objeto em content.json
Next steps?!
Com conteúdo textual e imagens devidamente providenciadas, é hora de começar a montar o video.
Mostro como fiz, no próximo post!
Abraço!