Armazenamento de Imagem Colorida (Array com 03 dimensoes) em um Dataframe

Home Fóruns Fórum Visão Computacional: O Guia Completo Armazenamento de Imagem Colorida (Array com 03 dimensoes) em um Dataframe

Visualizando 4 posts - 1 até 4 (de 4 do total)
  • Autor
    Posts
  • #45673

    Olá Pessoal, estou necessitando de ajuda.

     

    Estou querendo armazenar as imagens em um dataframe para utiliza-lo como o repositorio de imagens. Estou usando o código abaixo, entretanto, estou sofrendo com a performance

    # Cadastrar usuario no Dataframe
    def cadastra_dataframe(full_name,imagem):
    nome = []
    imagem_lista = []

    for img in imagem:
    nome.append(full_name)
    imagem_lista.append(img.tolist())

    # abrindo df exitente
    df = pd.read_csv(‘usuario.csv’)

    # Dados para ser incluído o dataframe existente
    dados = {‘full_name’: nome,  ‘imagem’: imagem_lista}
    dados = pd.DataFrame(dados)

    df = pd.concat([df, dados], ignore_index = True)
    df.to_csv(‘usuario.csv’, index=False)
    return 0

    Quando vou exibir as imagens gravadas no dataframe, vem o sofrimento 🙂

    dados_df = pd.read_csv(‘usuario.csv’)

    # Itera sobre cada linha do DataFrame para exibir as imagens
    for i in range(0, len(dados_df)):

    full_name = dados_df[‘full_name’][i]
    #print(full_name)

    inicio = time.time()
    imagens_lista = ast.literal_eval(dados_df[‘imagem’][i])
    fim = time.time()
    execucao = fim – inicio
    print(f’tempo de execucao : {execucao:.6f} segundos’) # Esta execução no meu notebook está levando cerca de 4 seg

    inicio = time.time()
    imagem_array = np.array(imagens_lista, dtype=np.uint8)
    fim = time.time()
    execucao = fim – inicio
    print(f’tempo da segunda execucao : {execucao:.6f} segundos’)

    #cv.imshow(‘Imagem Recuperada’, imagem_array)
    #cv.waitKey(0)
    #cv.destroyAllWindows()

     

    #45677
    Gabriel Alves
    Moderador

      Olá Cesar!

      Para melhorar a performance ao armazenar e exibir imagens coloridas em um DataFrame eu acredito que algumas mudanças podem ser feitas na sua abordagem.

      No código de cadastro de usuários no DataFrame, atualmente você está convertendo cada imagem em uma lista antes de armazenar, o que pode ser bem ineficiente em termos de espaço e tempo de execução. Além disso, ao ler as imagens do DataFrame, você está usando ast.literal_eval para converter as strings de volta em listas, o que também pode vir a ser extremamente lento.

      Uma abordagem mais eficiente seria armazenar as imagens codificadas em base64 diretamente no dataframe. Isso não só melhora a performance, mas também facilita a manipulação dos dados.

      E codificando as imagens em base64 você reduz o tempo necessário para converter entre diferentes formatos de dados. Armazenar imagens codificadas como strings base64 em um CSV pode ser mais eficiente do que armazenar listas de números, além de facilitar a manipulação dos dados. Isso deve resolver o problema de performance que você está enfrentando e tornar o processo de armazenamento e recuperação de imagens mais eficiente.

      Aqui está uma sugestão de código com base no que você informou:

      [ ... importações e restante do código ] 
      
      # Função para converter imagem para base64
      def image_to_base64(image):
        _, buffer = cv2.imencode('.jpg', image)
        image_base64 = base64.b64encode(buffer).decode('utf-8')
        return image_base64
      
      # Função para converter base64 para imagem
      def base64_to_image(image_base64):
        image_data = base64.b64decode(image_base64)
        image_np = np.frombuffer(image_data, dtype=np.uint8)
        image = cv2.imdecode(image_np, cv2.IMREAD_COLOR)
        return image
      
      # Cadastrar usuario no Dataframe
      def cadastra_dataframe(full_name, imagem):
        nome = [full_name]
        imagem_base64 = [image_to_base64(imagem)]
      
        # Abrindo df existente
        df = pd.read_csv('usuario.csv')
      
        # Dados para ser incluído o dataframe existente
        dados = {'full_name': nome, 'imagem': imagem_base64}
        dados = pd.DataFrame(dados)
      
        df = pd.concat([df, dados], ignore_index=True)
        df.to_csv('usuario.csv', index=False)
      
      # Exibir as imagens gravadas no dataframe
      dados_df = pd.read_csv('usuario.csv')
      
      ### E para iterar sobre cada linha do DataFrame para exibir as imagens
      for i in range(len(dados_df)):
        full_name = dados_df['full_name'][i]
        print(full_name)
      
        inicio = time.time()
        imagem_base64 = dados_df['imagem'][i]
        imagem_array = base64_to_image(imagem_base64)
        fim = time.time()
        execucao = fim - inicio
        print(f'tempo de execucao : {execucao:.6f} segundos')
      
        cv2.imshow('Imagem Recuperada', imagem_array)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
      #45679

      Obrigado Gabriel, melhorou muito o tempo de processamento.

      Pesquisando um pouco mais, encontrei uma biblioteca pickle, nativa do python, e fiz uma comparação entre as duas bibliotecas

       

      Usando o código sugerido, usando a biblioteca base64, obtivemos:

      Tempo de execução para cadastrar 10 img usando base64: 0.221020 segundos

      Tempo de execucao para carregar e transformar em array 10 img usando base64: 0.020040 segundos

      Tamanho do arquivo armazenado em disco: 710 KB

       

      Usando o mesmo código, e utilizando a biblioteca pickle, obtivemos:

      Tempo de execucao para cadastrar 10 img usando pickle: 0.093708 segundos

      Tempo de execucao para carregar 10 img usando pickle: 0.000915 segundos (já que não é necessário a conversão

      Tamanho do arquivo armazenado em disco: 9.002 KB

       

      Qual das duas é a mais recomendada

      #45721
      Gabriel Alves
      Moderador

        Opa, que ótimo que melhorou bastante o desempenho!

        Comparando esses dois testes, dá para comprovar que ambas as abordagens têm suas vantagens e desvantagens. Usar base64 resulta em um arquivo significativamente menor (710 KB contra 9.002 KB com pickle), o que é vantajoso para armazenamento e transmissão de dados. No entanto, a performance de pickle é superior tanto no tempo de cadastro quanto carregamento e processamento.

        Portanto, a escolha entre as duas depende das suas prioridades. Se o objetivo principal for economizar espaço de armazenamento e garantir portabilidade, base64 é a melhor opção. Por outro lado, se a prioridade for performance e rapidez na leitura e escrita de dados, pickle é mais recomendado. Avalie o que é mais importante para seu projeto e escolha a abordagem que melhor se alinha às suas necessidades. Caso escolha a pickle devido à velocidade, você pode ainda tentar aplicar técnicas para reduzir o tamanho em disco, como explicado nesse artigo por exemplo.

      Visualizando 4 posts - 1 até 4 (de 4 do total)
      • Você deve fazer login para responder a este tópico.