[英]Convert list of integers to list of bits Python
我目前正在嘗試將視頻數據饋送到激光器(我們使用激光器進行通信)。 激光器通過調制工作,我們總共有 2 個狀態,相當於 0 和 1。因此,為了向激光器提供視頻數據,我首先需要將其轉換為位。 我從帶有 openCV 的網絡攝像頭獲得的幀由 2D arrays 表示,其中包含 8 位整數以獲得灰度圖像。 目前,我正在對這些 arrays 進行如下改造:
if __name__ == '__main__':
video = Video()
frame = video.getFrameBits()
其中視頻 class 定義為:
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
並且位 function 的 int 為:
def intToBits(x):
send = str(bin(x).lstrip('0b'))
send = send.zfill(8)
return send
我使用 intToBits function 的原因是因為我希望能夠將這個我稱為frame
的數組直接輸入激光器。 在當前的實現中,前導零不會從數組中截斷。 所以我得到一個 output 像: [10010101,10010100,10010101,10010111,10010110,10010101,10010100,10010001,10010001,01011000,...]
整個代碼的問題在於它在我可用的微控制器上運行得太慢了。 獲得一幀大約需要 5 秒,這是相當糟糕的。 我的第一個想法是去掉getFrameBits中嵌套的for循環,如下:
frame_bits = [intToBits(pixel) for row in frame for pixel in row]
這確實縮短了時間,但我想看看是否可以進一步改進。 我們仍然需要大約 1 秒來獲取幀,這更好,但我們期望更大的采樣率。
我的下一個想法是在 C 中編寫代碼並在 Python 中運行它,但我對 C 不太熟悉。 因此,雖然我願意這樣做,但我想確保這是正確的方向。
還有其他方法可以優化此代碼嗎?
謝謝!
除了一點點矢量化 - 無需編寫 C 代碼,以防 numpy 的引擎蓋下內置代碼已經寫在 Z0D61F8370CAD1D412F70B84D143E2 中。
import numpy as np
import cProfile, pstats, io
input_size = 1000000
#since I don't have your image, I made do with a random sample of 8bit numbers.
test_input = np.random.randint(0, 256, input_size)
#to check that we get the correct result, set input_size to 2
#and uncomment the line below
#test_input = [255, 7]
#your function for the speed comparison purposes
def intToBits(x):
send = str(bin(x).lstrip('0b'))
send = send.zfill(8)
return send
#note, that in this case x is the whole array, not just one number
#to make the full use of the vectorization
#also the output is not a bitfield, but a string
#the > 0 at the end is to convert the result into booleans.
#strictly speaking it isn't necessary if you are fine with 0 1 integers.
def binary_repr(x):
return(
np.dstack((
np.bitwise_and(x, 0b10000000) >> 7,
np.bitwise_and(x, 0b1000000) >> 6,
np.bitwise_and(x, 0b100000) >> 5,
np.bitwise_and(x, 0b10000) >> 4,
np.bitwise_and(x, 0b1000) >> 3,
np.bitwise_and(x, 0b100) >> 2,
np.bitwise_and(x, 0b10) >> 1,
np.bitwise_and(x, 0b1)
)).flatten() > 0)
#starting the profiler.
pr = cProfile.Profile()
pr.enable()
#the two computations that we want to compare
a = []
for i in range(input_size):
a.append(intToBits(test_input[i]))
print(a)
b = binary_repr(test_input)
print(b)
#the comparison
sortby = 'cumulative'
pr.disable()
s = io.StringIO()
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
ps.print_stats()
print(s.getvalue())
為了完整起見,分析器結果:
ncalls tottime percall cumtime percall filename:lineno(function)
1000000 0.577 0.000 0.920 0.000 (intToBits)
2 0.195 0.098 0.195 0.098 {built-in method builtins.print}
1000000 0.125 0.000 0.125 0.000 {method 'lstrip' of 'str' objects}
1000000 0.119 0.000 0.119 0.000 {built-in method builtins.bin}
1000000 0.099 0.000 0.099 0.000 {method 'zfill' of 'str' objects}
1000008 0.082 0.000 0.082 0.000 {method 'append' of 'list' objects}
1 0.030 0.030 0.062 0.062 (binary_repr)
如您所見,即使生成數據也比切換到按位表示需要更多時間。 雖然您需要稍微修改一下以適應您的代碼,因為 output 格式有點不同 - 一個大數組而不是 arrays 數組 - 它應該非常值得。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.