上一篇文章留下了一个问题,就是如何解决垂直线变斜的问题。
这个问题本来应该从通信上来解决,找出行同步信号,然后在这个信号处换行。
但是实际并不好做,因为hdmi并不是无线通信标准,没有这方面的资料。
因此,我打算用图像处理的方式来解决。即找出原始画面的规律,然后从画面上直观地做一些修改,来改善效果。
我本来考虑过给图形做仿射变换,相当于旋转图像,但是我估计效果不会太好。
后来我想了想,目前的问题无非就是每个行开始处有个offset的问题。我只要把这个offset位置的像素点挪到最开头那个点就行。还有个问题是这个offset对于每一行来说都是在变化的,幸运的是变化的趋势是固定的,比如下一行都比上一行offset大了一个固定的值。这样就很容易搞定了。
当然实际做的时候还会碰到各种各样的细节问题,比如offset后的像素挪到了左侧后,这一行offset前的像素点是不是就直接扔掉了?显然,不能这样,不然每行的右侧都会缺东西。事实上每一行的右侧都是用下一行offset左侧的像素点补上去的。
还有就是如果一下子写不出循环也不要紧,建议先参考我注释里写的那样,想象一种比较特殊的情形,然后把特殊情形的实际的像素点位置等数字写出来,然后从这些像素点之间的关系做一个归纳,找出他们的规律,然后再写循环,就会方便不少。
实际写代码过程中还会碰到各种各样的问题:
比如range(0,10)是从0到9,如果要包含10就需要改为range(0,10+1)。
另外offset如果不停减去一个固定值,可能会小于0,导致某几个取值超过边界,这时候可以想象如果一行的offset位置是0,那下一行的位置可以认为是-1(小于0),也可以认为在屏幕的右侧出现,此时就是行宽-1。也就是说可以把行宽作为周期,在offset小于0时给它补上去。同理,如果offset不停加上一个固定值也可能超出行宽,这时给它减去一个周期(行宽)就行。这就是我在代码56~59行做的事情。如果你不理解你可以把这部分删除,看看程序是否报错,再把对应x,y,offset的变量打印出来,看看为啥这些变量在这个取值时会报错就能理解我为啥要这么写了。
- from pylab import *
- from rtlsdr import *
- import cv2
-
-
- sdr = RtlSdr()
- # configure device
- sdr.sample_rate = 1.951047e6
- sdr.center_freq = 395.991e6
- sdr.gain = 60
- # init for opencv
- x = 0
- y = 0
- img = np.zeros((600,600,1), np.uint8)
- img_to_show = np.zeros((600,600,1), np.uint8)
-
- coarse_length_of_line = 580
- fine_tune_of_offset_variation = -2
- height_to_draw = 500
-
- while True:
- samples = sdr.read_samples(1024*100) #type(sample) is numpy.complex128
-
- for sample in samples:
- mag = np.sqrt( sample.imag * sample.imag + sample.real * sample.real)
- value = mag * 255 * 10 #type(value) numpy.float64
-
- img[y, x] = value
- img[y, x + 1] = value
- img[y, x + 2] = value
- img[y, x + 3] = value
- img[y, x + 4] = value
- img[y, x + 5] = value
- img[y, x + 6] = value
- img[y, x + 7] = value
- img[y, x + 8] = value
- img[y, x + 9] = value
-
- x = x + 10
- if (x >= coarse_length_of_line):
- x = 0
- y = y + 1
- if (y >= height_to_draw):
- y = 0
-
-
- offset = 0
- for j in range(0, height_to_draw):
- for i in range(0, coarse_length_of_line - offset + 1): # contains 0 and coarse_length_of_line - offset
- img_to_show[j, i] = img[j, i + offset]
-
- for i in range(coarse_length_of_line - offset + 1, coarse_length_of_line + 1):
- img_to_show[j, i] = img[j + 1, i + offset - coarse_length_of_line - 1]
-
- offset = offset + fine_tune_of_offset_variation
- if (offset < 0):
- offset = offset + coarse_length_of_line
- elif (offset > coarse_length_of_line):
- offset = offset - coarse_length_of_line
-
- '''
- img_to_show[0, 0] = img[0, 50]
- img_to_show[0, 1] = img[0, 51]
- ...
- img_to_show[0, 530] = img[0, 580]
- img_to_show[0, 531] = img[1, 0]
- ...
- img_to_show[0, 580] = img[1, 49]
- img_to_show[1, 0] = img[1, 45]
- img_to_show[1, 1] = img[1, 46]
- ...
- img_to_show[1, 535] = img[1, 580]
- img_to_show[1, 536] = img[2, 0]
- ...
- img_to_show[1, 580] = img[2, 44]
- '''
-
-
- cv2.imshow("HDMI", img)
- cv2.imshow("HDMI2", img_to_show)
- if(cv2.waitKey(10)==27):
- break
-
- sdr.close()
我的程序还是有不少要优化的地方,比如纠正后的画面中间老是会有一条细斜线,如果大家知道为啥可以告诉我。
另外就是如果能找出hdmi的行同步和帧同步信号对无线电的实际影响并用于纠偏就更好了。
本文代码实际效果:
SDR接收HDMI泄漏3 极简代码实现tempestsdr_哔哩哔哩_bilibili
https://www.bilibili.com/video/BV1U34y1H7YD