I am currently trying to feed video data to a laser (we use the laser for communications). The laser works through modulation, where we have 2 states total, equivalent to 0 and 1. Hence, in order for me to feed the laser the video data, I first need to convert it to bits. My frames, which I get from a webcam with openCV, are represented by 2D arrays which contain 8-bit integers to get a greyscale image. Currently, I am transforming these arrays as follows:
if __name__ == '__main__':
video = Video()
frame = video.getFrameBits()
Where the Video class is defined as:
class Video:
# scale_percent: percent of original size of frame
def __init__(self, scale_percent=100):
self.cap = cv2.VideoCapture(0)
# Get one frame to figure out sizing constraints
_, frame = self.cap.read()
width = int(frame.shape[1] * scale_percent / 100)
height = int(frame.shape[0] * scale_percent / 100)
self.dim = (width, height)
# color: If true show color frames. Not yet implemented
def getFrame(self, color=False):
_, frame = self.cap.read()
frame = cv2.resize(frame, self.dim, interpolation=cv2.INTER_AREA)
if not color:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
return gray
def getFrameBits(self):
frame = self.getFrame()
for row in frame:
for pixel in row:
frame_bits.append(intToBits(pixel))
return frame_bits
And the int to bits function as:
def intToBits(x):
send = str(bin(x).lstrip('0b'))
send = send.zfill(8)
return send
The reason I am using the intToBits function is because I would like to be able to take this array that I called frame, and feed it directly into the laser. With the current implementation, the leading zeros are not truncated from the array. So I get an output like:
[10010101,10010100,10010101,10010111,10010110,10010101,10010100,10010001,10010001,01011000,...]
The problem with this whole code is that it runs much too slow on the micro-controller I have available. It takes about 5 seconds to get a single frame, which is rather abysmal. My first thought is to get rid of the nested for loop in getFrameBits, as follows:
frame_bits = [intToBits(pixel) for row in frame for pixel in row]
This did improve the time, but I would like to see if it can be improved further. We are still taking about 1 second to get the frame, which is better, but we are expecting a larger sampling rate.
My next idea would be to code this in C and run it in Python, but I am not too familiar with C. So whilst I would be willing to do this, I wanted to make sure it was the correct direction to take.
Are there some more ways I can optimize this code?
Thanks!