Building a gray scale image via a numpy array from ultrasonic sensor values

Hi all,
I have an ultrasonic sensor. I want to convert its distance readings to an image.

I have the readings stored in a numpy array but how do I construct the array so that it is a valid gray scale image?

Here is the code I have so far.

import maxSonarTTY
import numpy as np
import cv2

def scale_list(l, to_min, to_max):
    return [scale_number(i, to_min, to_max, min(l), max(l)) for i in l]
m=0
raw_sonar_readings=[]
while True:
    
    m=maxSonarTTY.measure("/dev/ttyUSB0")
    raw_sonar_readings.append(m)
    if len(raw_sonar_readings)==64:
        #using one of the functions found at https://stackoverflow.com/questions/929103/convert-a-number-range-to-another-range-maintaining-ratio
        scaled_readings=scale_list(raw_sonar_readings,0,255)
        temp_array=np.array(scaled_readings,dtype=numpy.uint8)
        cv2.imwrite('image_img.png', temp_array)
        print("image written")
        raw_sonar_readings.clear()

what makes you think your code doesn’t do what you want?

what .shape and .dtype does temp_array have?

Hi,
The data type is uint8. temp_array is a numpy array. I am feeding it the sensor values from a list.
My images are 0 bytes in size and from my reading, just feeding values into a numpy array and writing them out via imgwrite will not do the job since an additional channel for each pixel is missing.
I read posts at the following link.
How to convert a python numpy array to an RGB image with Opencv 2.4? - Stack Overflow

I am scaling the sensor values to between 0 and 255.

what is the .shape of temp_array?

your files are. because whatever you’re giving to the imwrite call is malformed.

uh yes it will, if the array has the right shape and dtype.

MRE is required.

the code you present is missing some definitions.

MRE” also means you must replace/mock all the serial stuff. nobody except you has this hardware device. insert the required data so the script runs standalone.

Hi,
The shape of temp_array is 64.
I have created minimum reproducible code below.

import random
import maxSonarTTY
import numpy as np
import cv2
def scale_number(unscaled, to_min, to_max, from_min, from_max):
    return (to_max-to_min)*(unscaled-from_min)/(from_max-from_min)+to_min

def scale_list(l, to_min, to_max):
    return [scale_number(i, to_min, to_max, min(l), max(l)) for i in l]
m=0
raw_sonar_readings=[]
#Warning, this program goes into an infinite loop. Break out of it by hitting ctrl+c
while True:
    
    #m=maxSonarTTY.measure("/dev/ttyUSB0") #Commenting out this line to create a mre
    m=random.uniform(500, 5000) #minik the distance values from the ultrasonic sensor
    raw_sonar_readings.append(m)
    if len(raw_sonar_readings)==64:
        #using one of the functions found at https://stackoverflow.com/questions/929103/convert-a-number-range-to-another-range-maintaining-ratio
        scaled_readings=scale_list(raw_sonar_readings,0,255)
        temp_array=np.array(scaled_readings,dtype=np.uint8)
        print("shape of array=",temp_array.shape)
        cv2.imwrite('image_img.png', temp_array)
        print("image written")
        raw_sonar_readings.clear()

impossible. that’s a single number, not a tuple. a shape is always a tuple. what precisely is the output of print(temp_array.shape)?

you don’t appear to make any attempt to shape your array into an “image” shape, which has (height, width, channels) shape.

why should imwrite be able to handle a flat list of values? that’s not a picture, that’s a series of sensor readings.

perhaps you shouldn’t use OpenCV at all. it is for computer vision.

you appear to want to write a series of sensor values into a text file or something. Python can do that with built-in facilities.

Hi,

I need to create the image by hand so to speak because I eventually want to pass it to the Meijer algorithm. An implementation of the same using a camera is at the following link.
https://www.seeingwithsound.com/hificode_OpenCV.py

I have made some progress after reading your messages and doing some more reading. See below for a minimum reusable implementation.
Note:
I have tried playing the array values which sort of works in the sense that I get different clicks as I move the sensor around.

The shape of the array is 64 64.

import sys import random import maxSonarTTY import numpy as np import cv2 import sounddevice as sd def scale_number(unscaled, to_min, to_max, from_min, from_max): return (to_max-to_min)*(unscaled-from_min)/(from_max-from_min)+to_min

def scale_list(l, to_min, to_max):
return [scale_number(i, to_min, to_max, min(l), max(l)) for i in l]
m=0
raw_sonar_readings=
fs = 44100
#Warning, this program goes into an infinite loop. Break out of it by hitting ctrl+c
while True:

#m=maxSonarTTY.measure("/dev/ttyUSB0") #Commenting out this line to create a mre
m=random.uniform(500, 5000) #minik the distance values from the ultrasonic sensor
raw_sonar_readings.append(m)
if len(raw_sonar_readings)==64:
    #using one of the functions found at https://stackoverflow.com/questions/929103/convert-a-number-range-to-another-range-maintaining-ratio
    scaled_readings=scale_list(raw_sonar_readings,0,255)
    image_array=np.empty([64, 64],np.uint8)
    for lc in range(len(scaled_readings)):
        scaled_readings_value=scaled_readings[lc]
        image_array[lc][lc]=scaled_readings_value

    print("shape of array=",image_array.shape)
    
    cv2.imwrite('image_img.png', image_array)
    sd.play(np.array(raw_sonar_readings,np.uint8), fs)
    print("image written")
    raw_sonar_readings.clear()