avatarMichael King

Summary

The article presents a method for storing and retrieving Numpy arrays in a MySQL database by converting them to PNG images using Python.

Abstract

The author describes a solution to a challenge they faced with storing large Numpy arrays and matrices in

An amazingly simple way to store and retrieve Numpy arrays in MySQL database via PNG conversion in Python

Sometime ago I was facing a challenge which involved processing of huge quantities of Numpy arrays and matrices. The data sets were grouped in clusters and nested sub categories. And because the data sets were required to be accessible via Internet I was looking for an easiest way to store them in MySQL database.

Photo by Kevin Ku on Unsplash

Let’s start with the road map

Numpy array to SQL

Import libraries for data handling

import mysql.connector
import os
import numpy as np
from imgarray import save_array_img, load_array_img
from os import fsync

Write your first function, which makes sure that data is written to disk, so that buffering doesn’t influence the timings.

def sync(fh):
   fh.flush()
   fsync(fh.fileno())
   return True

Write the next function which converts any given Numpy data set into PNG image. As arguments we will be using numpy array name and save path where the new image will be stored

def save_array_to_PNG(numpy_array, save_path):
    with open(save_path, 'wb+') as fh:
        save_array_img(numpy_array, save_path, img_format='png')
        sync(fh)

    return save_path

The next function is pretty short and it converts the image file into binary format, which we will need for future processing in SQL

def convertToBinaryData(filename):
    with open(filename, 'rb') as file:
        binaryData = file.read()
    return binaryData

The following function will handle the image upload to your MySQL database. And I assume that you already have set up the database table with a column for image storage (column type = Blob).

def insertBLOB(png_image):
    try:
        connection = mysql.connector.connect(
            user='Your_user_name',
            password='Your_MySQL_password',
            host='host_address',
            database='database_name')

        sql_table = 'your_table_name'
        image_column_name = 'your_blob_column_name'

        file = convertToBinaryData(png_image)
        
        cursor = connection.cursor()
        sql_insert_blob_query = "INSERT INTO " + sql_table + " (" + image_column_name + ") VALUES (" + file + ")"
        result = cursor.execute(sql_insert_blob_query)
        connection.commit()

    except mysql.connector.Error as error:
        print("Failed inserting BLOB data into MySQL table {}".format(error))

    finally:
        if (connection.is_connected()):
            cursor.close()
            connection.close()
            print("MySQL connection is closed")

That was easy! We just have set up the functions which will handle the conversion and upload to MySQL database.

In the following steps, I will show you how to retrieve this data from SQL and convert it back to Numpy array format. But let’s start with process road map first.

MySQL data to Numpy array

The next function will enable the conversion of binary object to proper file format on your hard drive.

def write_file(data, filename):
    # Convert binary data to proper format and write it on Hard Disk
    with open(filename, 'wb') as file:
        file.write(data)

And the very last function will retrieve the PNG image from MySQL database and convert it back to Numpy array

def readBLOB(save_file_as, ID):
    try:
        connection = mysql.connector.connect(
            user='Your_user_name',
            password='Your_MySQL_password',
            host='host_address',
            database='database_name')

        sql_table = 'your_table_name'
        image_column_name = 'your_blob_column_name'

        cursor = connection.cursor()
        sql_fetch_blob_query = "SELECT " + image_column_name + " from " + sql_table + " where ID = '"+ str(ID)
        cursor.execute(sql_fetch_blob_query)
        record = cursor.fetchone()
        
        file = record[0]
        write_file(file, save_file_as)
        numpy_arr_sql = load_array_img(save_file_as)

        return numpy_arr_sql

Done! We have managed the whole process of conversion from Numoy array to SQL and back to Numpy array.

And here is an example how the whole code could look like.

import mysql.connector
import os
import numpy as np
from imgarray import save_array_img, load_array_img
from os import fsync

def sync(fh):
   fh.flush()
   fsync(fh.fileno())
   return True

def save_array_to_PNG(numpy_array, save_path):
    with open(save_path, 'wb+') as fh:
        save_array_img(numpy_array, save_path, img_format='png')
        sync(fh)

    return save_path

def convertToBinaryData(filename):
    with open(filename, 'rb') as file:
        binaryData = file.read()
    return binaryData

def insertBLOB(png_image):
    try:
        connection = mysql.connector.connect(
            user='Your_user_name',
            password='Your_MySQL_password',
            host='host_address',
            database='database_name')

        sql_table = 'your_table_name'
        image_column_name = 'your_blob_column_name'

        file = convertToBinaryData(png_image)

        cursor = connection.cursor()
        sql_insert_blob_query = "INSERT INTO " + sql_table + " (" + image_column_name + ") VALUES (" + file + ")"
        result = cursor.execute(sql_insert_blob_query)
        connection.commit()

    except mysql.connector.Error as error:
        print("Failed inserting BLOB data into MySQL table {}".format(error))

    finally:
        if (connection.is_connected()):
            cursor.close()
            connection.close()
            print("MySQL connection is closed"


def write_file(data, filename):
    # Convert binary data to proper format and write it on Hard Disk
    with open(filename, 'wb') as file:
        file.write(data)

def readBLOB(save_file_as, ID):
    try:
        connection = mysql.connector.connect(
            user='Your_user_name',
            password='Your_MySQL_password',
            host='host_address',
            database='database_name')

        sql_table = 'your_table_name'
        image_column_name = 'your_blob_column_name'

        cursor = connection.cursor()
        sql_fetch_blob_query = "SELECT " + image_column_name + " from " + sql_table + " where ID = '"+ str(ID)
        cursor.execute(sql_fetch_blob_query)
        record = cursor.fetchone()

        file = record[0]
        write_file(file, save_file_as)
        numpy_arr_sql = load_array_img(save_file_as)

        return numpy_arr_sql

    
# write Numpy array into MySQL database
my_numpy_array = np.ones(150,150)
insertBLOB(save_array_to_PNG(my_numpy_array, 'image.png'))

#retrieve numpy array from MySQL
my_numpy_array_from_SQL = readBLOB('image_from_SQL.png', ID = 1)

And if you’re feeling particularly generous, you could buy me a coffee at www.buymeacoffee.com/kingmichael. Your support would greatly help in keeping me motivated and writing articles that you love.

Programming
Numpy
Python
MySQL
Sql
Recommended from ReadMedium