如果不会用python,可以看看“北京尚学堂”的python视频,b站就有高清的
软件为Pycharm,内置python 3.7解释器
需要用pyserial,opencv-python这两个模块,模块名可直接复制,均为小写
第一步:使用opencv打开图片
import cv2 # 引入opencv模块
import serial # 串口模块
def ON_Figure():
img = cv2.imread('E:/figure/ph.png') # 加载E盘figure文件夹下的ph.png图片
# 后缀要有,img变量名任取
cv2.imshow('figure', img) # 显示图片,窗口名:figure,数据来源为img
print(type(img)) # 打印img的类型:numpy.ndarry
print(img) # 打印img内的数据
cv2.waitKey(0) # 无限延时,如果出问题就,(x)就留空,x大于0,就延时x毫秒
cv2.waitKey()放在最后
不了解numpy.ndarray这个类型,只用过数组,但用起来到时差不多,但列表无法被opencv显示,只能显示numpy.ndarray
实际上打开图片只用到函数下面的两行
img内的数据三个一组,RGB的数据,至于是不是R,G,B这么排的我也不知道
第二步:等比例缩放图片
dst = cv2.resize(img, (333, 1000)) # cv2.resize(img,(width,high))调整大小
cv2.imshow('figure2', dst)
cv2.waitKey(0) # 无限延时,使图片能显示
延时放到最后。width为宽,high为高,只能为整数,图片可以比原来大,也可小,也可变形
知道怎么用了以后,获取图片信息
imginfo = img.shape # 读取信息
print(imginfo) # 得到数据,(h,w,x)h为高,w为宽,x为3维——RGB三种颜色,每个像素都由RGB组成
得到的数据类型为元组,就是只读列表
计算高度为64时的等比例宽度
va1 = imginfo[0] / 64 # 计算高是64的几倍,带小数,元组的读取方式和列表一样
high = int(imginfo[0] / va1) # 计算变化后的高
width = int(imginfo[1] / va1) # 宽
print(width,high)
dst = cv2.resize(img, (width, high)) # 宽和高只能取整数,不支持浮点,而且像素只可能是整数
cv2.imshow('resize', dst)
假如,高为128,除以64等于2,那么缩小后的高就用128除以2,会得到64。128/60=?,?x 60=128
用int转换,把浮点数转成整数,int会直接砍掉小数,没有4舍5入
第三步:把图转成黑白两色
gray_lwpCV =cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY) # 转灰度图,gray_lwpCV为变量名
print(gray_lwpCV)
cv2.imshow('figure3', gray_lwpCV)
这个是转成灰度图,转完后就剩下每个像素的灰度值,RGB信息没有了,灰度是0~255,黑——灰——白,值越大越亮
得到灰度后,判断其值是否大于127,大于127就置255(白),否则置0(黑)
for i in range(high):
for j in range(width):
if gray_lwpCV[i, j] > 127: # gray_lwpCV[高, 宽]
gray_lwpCV[i, j] = 255
else:
gray_lwpCV[i, j] = 0
cv2.imshow('figure4', gray_lwpCV)
这个时候再看图片的时候就是黑白色了
但是这时候的数据很多,64x128个的数据普通的单片机处理慢,何况数据是快速刷新的
需要转成8x128,显示黑白两色只要0和1
oled = [[0 for i in range(128)] for i in range(8)] # 创建[8][128]的列表。
for i in range(high):
Ic = i % 8 # 0~7循环,共循环8次,原数据有64行
for j in range(width):
if gray_lwpCV[i, j] < 128:
oled[i // 8][j] |= 0x01 << Ic # i//8就是0~7,共8行。这里用0x01<>Ic跟据你用单片机控制的屏幕有关
这里我用的屏幕显示是普通的12864,每8个点为一次数据,8个像素为竖向排列,低位在上,高位在下
我用0x01< 这段程序的作用就是把原来8行的数据转为1行,原来8个纵向的点分别用0和255来表示,,用到8x8bit,现在只要8bit就能代表8个点。建议用用Pycharm的调试,看看数据都是怎么排的 这种,[[0] * 3] * 3创建列表不能用,给一个赋值,其他的都会赋值,不知道为啥,希望有人说说 至此,数据处理基本完成,但是串口发送可是个大问题,跟着寥寥无几的资料和根本不算教程的教程摸索,头大。有人直接贴出代码,啥说明没有,连最起码的注释都不写,复制过来都不知道怎么用 一般只需要设置这三个,超时时间意思是接收到数据后就开始计时,如果超过时间就返回数据,没超过就等待下一个数据,每收到一帧数据刷新计时,时间单位为秒,如timeout=0.5。None就是一直在接收 关键就是'b'这个东西,在Python3里新加的,原来2里直接用字符串就行了。3进步了,但是write函数没进步 b的作用就是把字母换成对应的16进制,ASCII码里的,0~255的范围,如果要发送的不在ASCII码里的要用到编码转换,比如中文,这里就不说了 只发送字母倒没啥,但是发送16进制,呵呵 ser.write(b'\x30')发送的就是0x30,\x是python的16进制识别符,类似于0x,但是\x不能写在普通字符串里,发送多个就不行了 如果要发送多个,把hvol换成列表,用循环发送 必须经过这种转换,或者用utf-8编码转换,但涉及到字符串的更改,不好使。 8x128的数据有了,发送10进制的方法有了,就简单了,循环发送就可以了 只需用到没注释的地方,注释的地方也很重要,但这里不是它发挥的地方 关于51的程序我只贴有用的,我用的时89c52,19200bps,测试正常 先开51,后运行python 会在下一篇里说怎么用51显示视频,跟这个显示图片差不多 https://pan.baidu.com/s/1I39Y1mU-_L19WgbwNeINMgser = serial.Serial('com2', 19200, timeout=None) # 必须用com1这种格式,57600bps,超时:无
print(ser) # 打印串口的各种设置状态
print(ser.isOpen()) # 检查串口是否打开
ser.write(b'hello!') # 发送hello!
hvol = 48 # 这里是10进制
hhex = '%02x' % hvol # 以16进制表示,不带前面的‘0x’,输出一个字符串,不足两个字符前面补0如,int类型的48,转成str类型的'30'
ser.write(bytes.fromhex(hhex)) # bytes.fromhex(hhex)返回一个 b'n'字符串,如b'0',n为该16进制对应的ascii码,hhex为字符串,hhex='30'
for i in range(8):
#str1 = b'start' + (bytes.fromhex('%02x' % i)) # 字符串(str类型,就是Unicode解码16进制出来的)编码成bytes(就是ascii码),把被解码的16进制重新编码回去。b'0'被转成\x30发送,\x是python的16进制标识码,和0x一样
#ser.write(str1) # 只能发送str
for j in range(128):
hhex = '%02x' % oled[i][j] # 以16进制表示,不带前面的‘0x’,输出一个字符串,不足两个字符前面补0如,int类型的48,转成str类型的'30'
ser.write(bytes.fromhex(hhex)) # bytes.fromhex(hhex)返回一个 b'n'字符串,n为该16进制对应的ascii码,如b'0',hhex为字符串,hhex='30'
'''if j == 127:
while True:
ll = ser.read(5)
if ll == b'hello': # 读到的是字母的16进制,对比时也要用16进制对比
break'''
u8 ix=0,iy=0
void Interrupt4() interrupt 4
{
if(RI)
{
RI=0;
DPByte(ix,iy,SBUF); // 每次写一个字节
ix++;
if(ix==128)ix=0,iy++; // 换行
}
}