获取棋盘格与标准模板在扫描仪上不同位置图片
简 介: 利用滑轨带动测量模板在扫描仪上滑动,通过识别结果来测试扫描仪沿着横向和纵向变化的情况。对于V370,它的横向和纵向的变化极差都在0.05mm之内。
关键词
: 扫描仪,V370,方差
Contents
§00 背景介绍
普通的扫描仪在获取一般图片的过程中,由于平移以及光学失真所噪声的图片变形都在可以容忍的范围之内,但基于扫描仪制作的分析仪测试仪器,比如阴影圈测量仪,就需要对于扫描仪可能产生的随机和系统误差进行测试。
利用滑轨带动标准图片在扫描仪上不同位置运动,获取后期的图片之后进行处理,便可以获得扫描仪不同位置上的测量失真。
§01 测量方案
1.1 扫描与移动
1.1.1 扫描仪
利用 EPSON Perfection V370 扫描仪来获取标准测量物在不同位置上的扫描图片。利用扫描仪自身所带的扫描程序 通过Python编程进行自动扫描阴影圈模板在不同位置上的图片 。
▲ 图1.1 V370扫描过程
扫描仪 BENQ 5560 由于没有能够成功在实验计算机上安装对应的驱动程序,所以这次实验只使用V370完成图片的社区。
1.1.2 滑轨控制
用于移动测量物(棋盘格、阴影圈模板)的滑轨使用 蜗杆单轨滑轨 ,利用它移动测量物在扫描仪表面移动。这个蜗杆滑轨利用 无触点感应行程开关 SN04-N 进行极限控制。具有0.891米的 形成控制。
▲ 图1.1.2 实验平台上的蜗杆滑轨与控制器
现在利用 基于ESP8266步进电机控制器 驱动滑轨运行。
- 最大行程:0.891米
- 移动步数:18000
▲ 图 滑轨在移动
1.1.3 固定阴影圈模板与滑轨
利用杠杆将滑轨与模板进行相连,带动其在扫描仪上滑动。
▲ 图1.1.4 利用杠杆将滑轨与模板进行相连,带动其在扫描仪上滑动
▲ 图 完成一次扫描成像
滑轨带动模板移动:
▲ 图 滑轨带动模板移动
1.2 扫描图片
1.2.1 扫描参数
- 滑块移动步数:4200
- 滑块移动次数:50,对应每次移动步数:84
蜗杆滑轨移动参数:
- 移动步数:3200
- 移动距离:15.8mm
▲ 图1.2.1 扫描后的图像
从上面扫描图来看,这种通过反射获得取的阴影圈图像由于出现镜面反射,亮度出现很大的变化。下面是通过喷涂红色油漆来改善这种情况。留在明天对这种喷涂阴影圈模板进行采集对比。
▲ 图1.2.2 在金属阴影圈表面喷涂黄色油漆
1.2.2 扫描程序
from headm import *
from tsmodule.tshardware import *epson_title = 'EPSON'
save_title = '文件保存设置'
process_title = '进程'def epsonScan():tspsendwindowkey(epson_title, "s", alt=1,noreturn=1)time.sleep(.1)if sum(tspgetwindowrect(save_title)) != 0:tspsendwindowkey(save_title, "\r", noreturn=1)while True:time.sleep(1)if(sum(tspgetwindowrect(process_title)) != 0): breaktspbeep(800, 20)while True:time.sleep(1)if(sum(tspgetwindowrect(process_title)) == 0): breaktspbeep(1800, 20)printf('\a')for i in range(100):printf("Scan time:%d"%i)epsonScan()rcccw(40)time.sleep(1)printf('\a')
1.2.3 扫描结果
下面获得了三个移动物体之后的扫描图片数据。它们分别是:
- 阴影圈移动图片:50
- 棋盘格往下移动:80
- 棋盘格对角线移动:100
▲ 图1.2.4 拍摄的移动的模板图片
▲ 图1.2.5 扫描棋盘格
▲ 图1.2.6 倾斜方向移动
1.2.4 图片数据存储
上面三组扫描图片,另外加上 扫描标准阴影圈模板 中的扫描图像,总共四个图片集合,存储在:
- CSDN 下载数据 : https://download.csdn.net/download/zhuoqingjoking97298/77568483
- AI Studio 扫描仪性能检测项目 : https://aistudio.baidu.com/aistudio/projectdetail/3438461
/home/aistudio/work/Scanner/ChessboardModel.zip
§02 数据处理
所有数据处理过程都在 AI Studio扫描仪性能检测项目 完成数据处理。
2.1 模板往下移动
2.1.1 处理代码
from headm import * # =
import cv2
from tqdm import tqdmmodeldown = '/home/aistudio/work/Scanner/Model-down'
chessboarddown = '/home/aistudio/work/Scanner/Chessboard-down'
chessboarddiagonal = '/home/aistudio/work/Scanner/Chessboard-diagonal'filedir = modeldownfiledim = sorted([s for s in os.listdir(filedir) if s.find('jpg') > 0])def modelArg(filename):img = cv2.imread(os.path.join(filedir,filename))gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1,50, param1=220, param2=30,minRadius=40, maxRadius=60)return img, circles[0]gifpath = '/home/aistudio/GIF'
if not os.path.isdir(gifpath):os.makedirs(gifpath)
gifdim = os.listdir(gifpath)
for f in gifdim:fn = os.path.join(gifpath, f)if os.path.isfile(fn):os.remove(fn)allcircle = []
for id,f in tqdm(enumerate(filedim)):img,circles = modelArg(f)img[where(img<50)]=50if len(circles) > 0:for c in circles:cv2.circle(img, (c[0], c[1]), int(c[-1]), (255, 0, 0), 6)plt.clf()plt.figure(figsize=(12,15))plt.imshow(img)savefile = os.path.join(gifpath, '%03d.jpg'%id)plt.savefig(savefile)allcircle.append(circles)
2.1.2 处理结果
▲ 图 检测所有的圆环
def circles2ratio(c):cm = mean(c, axis=0)rdim = [0]*4for cc in c:if cc[0] <= cm[0] and cc[1] <= cm[1]:rdim[0] = cc[2]elif cc[0] <= cm[0] and cc[1] > cm[1]:rdim[1] = cc[2]elif cc[0] > cm[0] and cc[1] <= cm[1]:rdim[2] = cc[2]else: rdim[3] = cc[2]return rdim
rdim1 = []
rdim2 = []
rdim3 = []
rdim4 = []for c in allcircle:r = circles2ratio(c)rdim1.append(r[0])rdim2.append(r[1])rdim3.append(r[2])rdim4.append(r[3])plt.clf()
plt.figure(figsize=(10,6))
plt.plot(rdim1, label='Ratio1')
plt.plot(rdim2, label='Ratio2')
plt.plot(rdim3, label='Ratio3')
plt.plot(rdim4, label='Ratio4')
plt.xlabel("n")
plt.ylabel("value")
plt.grid(True)
plt.tight_layout()
plt.legend(loc='upper right')
plt.savefig('/home/aistudio/stdout.jpg')
plt.show()
▲ 图2.1.2 求取结果分布
print("std(rdim1): {}".format(std(rdim1)),"std(rdim2): {}".format(std(rdim2)),"std(rdim3): {}".format(std(rdim3)),"std(rdim4): {}".format(std(rdim4)))plt.clf()
plt.figure(figsize=(10,6))
plt.hist(rdim1)
plt.hist(rdim2)
plt.hist(rdim3)
plt.hist(rdim4)plt.xlabel('Ratio')
plt.ylabel('Hist')
plt.grid(True)
plt.tight_layout()
plt.savefig('/home/aistudio/stdout.jpg')
▲ 图2.1.4 求取结果分布
std(rdim1): 0.4690808057785034
std(rdim2): 0.5530140995979309
std(rdim3): 0.6512018442153931
std(rdim4): 0.6946914792060852
2.2 棋盘格往下移
▲ 图2.2.1 扫描棋盘格
▲ 图 棋盘格往下移动
利用所有点的方差的平方根代表等效的圆的直径。设 (xi,yi),i=1,2,⋯,N\left( {x_i ,y_i } \right),i = 1,2, \cdots ,N(xi,yi),i=1,2,⋯,N 是所有采集到的的角点的位置。对应测量结果由下面公式给出:r=var(xi)+var(yi)r = \sqrt {{\mathop{\rm var}} \left( {x_i } \right) + {\mathop{\rm var}} \left( {y_i } \right)}r=var(xi)+var(yi)
下面给出了随着移动步数而变化的测量结果。
▲ 图2.2.2 格点标准方差变化
这是变化结果的分布。
▲ 图2.2.3 格点标准方差变化统计
极差范围:0.0254mm
std(sqrt(vdim)): 0.03459230065345764
2.3 棋盘格对角线平移
倾斜方向的移动反映了扫描仪左右方向与垂直方向发生面积形变的综合。
▲ 图 图像处理结果
▲ 图A2.3.2 测量结果随着运行变化情况
▲ 图2.3.2 面积统计分布
std(sqrt(vdim)): 0.07298741489648819
测量数据对应的极差:Δ=138.95−138.65150×25.4=0.051mm\Delta = {{138.95 - 138.65} \over {150}} \times 25.4 = 0.051mmΔ=150138.95−138.65×25.4=0.051mm
※ 处理总结 ※
利用滑轨带动测量模板在扫描仪上滑动,通过识别结果来测试扫描仪沿着横向和纵向变化的情况。对于V370,它的横向和纵向的变化极差都在0.05mm之内。
■ 相关文献链接:
- Epson Perfection V370 Photo图片扫描自动控制
- 扫描标准阴影圈模板
- 安装BENQSCANNER 5560驱动与测试扫描
- 蜗杆单轨滑轨
- 无触点感应行程开关 SN04-N
- 基于ESP8266 WiFi控制的步进升降机械平台
- 扫描后的棋盘格,用于测试对应的扫描仪的性能。-网络攻防文档类资源-CSDN文库
- AI Studio 扫描仪性能检测项目
● 相关图表链接:
- 图1.1 V370扫描过程
- 图1.1.2 实验平台上的蜗杆滑轨与控制器
- 图 滑轨在移动
- 图1.1.4 利用杠杆将滑轨与模板进行相连,带动其在扫描仪上滑动
- 图 完成一次扫描成像
- 图 滑轨带动模板移动
- 图1.2.1 扫描后的图像
- 图1.2.2 在金属阴影圈表面喷涂黄色油漆
- 图1.2.4 拍摄的移动的模板图片
- 图1.2.5 扫描棋盘格
- 图1.2.6 倾斜方向移动
- 图 检测所有的圆环
- 图2.1.2 求取结果分布
- 图2.1.4 求取结果分布
- 图 棋盘格往下移动
- 图2.2.2 格点标准方差变化
- 图2.2.3 格点标准方差变化统计
- 图 图像处理结果
- 图A2.3.2 测量结果随着运行变化情况
- 图2.3.2 面积统计分布
处理程序
处理阴影圈程序
#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# MODEL.PY -- by Dr. ZhuoQing 2022-01-23
#
# Note:
#============================================================from headm import * # =
import cv2
from tqdm import tqdmmodeldown = '/home/aistudio/work/Scanner/Model-down'
chessboarddown = '/home/aistudio/work/Scanner/Chessboard-down'
chessboarddiagonal = '/home/aistudio/work/Scanner/Chessboard-diagonal'#------------------------------------------------------------
filedir = modeldownfiledim = sorted([s for s in os.listdir(filedir) if s.find('jpg') > 0])
#printt(filedim)#------------------------------------------------------------
def modelArg(filename):img = cv2.imread(os.path.join(filedir,filename))gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1,50, param1=220, param2=30,minRadius=40, maxRadius=60)return img, circles[0]#------------------------------------------------------------gifpath = '/home/aistudio/GIF'
if not os.path.isdir(gifpath):os.makedirs(gifpath)
gifdim = os.listdir(gifpath)
for f in gifdim:fn = os.path.join(gifpath, f)if os.path.isfile(fn):os.remove(fn)#------------------------------------------------------------
allcircle = []
for id,f in tqdm(enumerate(filedim)):img,circles = modelArg(f)img[where(img<50)]=50if len(circles) > 0:for c in circles:cv2.circle(img, (c[0], c[1]), int(c[-1]), (255, 0, 0), 6)# printt(circles)plt.clf()plt.figure(figsize=(12,15))plt.imshow(img)
# plt.savefig('/home/aistudio/stdout.jpg')savefile = os.path.join(gifpath, '%03d.jpg'%id)plt.savefig(savefile)allcircle.append(circles)# break#------------------------------------------------------------
#printt(allcircle)def circles2ratio(c):cm = mean(c, axis=0)
# printt(cm:)rdim = [0]*4for cc in c:if cc[0] <= cm[0] and cc[1] <= cm[1]:rdim[0] = cc[2]elif cc[0] <= cm[0] and cc[1] > cm[1]:rdim[1] = cc[2]elif cc[0] > cm[0] and cc[1] <= cm[1]:rdim[2] = cc[2]else: rdim[3] = cc[2]return rdim#------------------------------------------------------------
rdim1 = []
rdim2 = []
rdim3 = []
rdim4 = []for c in allcircle:r = circles2ratio(c)
# printt(r:)rdim1.append(r[0])rdim2.append(r[1])rdim3.append(r[2])rdim4.append(r[3])plt.clf()
plt.figure(figsize=(10,6))
plt.plot(rdim1, label='Ratio1')
plt.plot(rdim2, label='Ratio2')
plt.plot(rdim3, label='Ratio3')
plt.plot(rdim4, label='Ratio4')
plt.xlabel("n")
plt.ylabel("value")
plt.grid(True)
plt.tight_layout()
plt.legend(loc='upper right')
plt.savefig('/home/aistudio/stdout.jpg')
plt.show()#------------------------------------------------------------
printt(std(rdim1):,std(rdim2):,std(rdim3):,std(rdim4):)plt.clf()
plt.figure(figsize=(10,6))
plt.hist(rdim1)
plt.hist(rdim2)
plt.hist(rdim3)
plt.hist(rdim4)plt.xlabel('Ratio')
plt.ylabel('Hist')
plt.grid(True)
plt.tight_layout()
plt.savefig('/home/aistudio/stdout.jpg')#------------------------------------------------------------
# END OF FILE : MODEL.PY
#============================================================
处理棋盘格
#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# CHESSB.PY -- by Dr. ZhuoQing 2022-01-24
#
# Note:
#============================================================from headm import * # =
import cv2
from tqdm import tqdmmodeldown = '/home/aistudio/work/Scanner/Model-down'
chessboarddown = '/home/aistudio/work/Scanner/Chessboard-down'
chessboarddiagonal = '/home/aistudio/work/Scanner/Chessboard-diagonal'#------------------------------------------------------------
filedir = chessboarddiagonalfiledim = sorted([s for s in os.listdir(filedir) if s.find('jpg') > 0])
#printt(filedim)CORNER_NUM = (11,8)def img2Corners(f):fn = os.path.join(filedir, f)img = cv2.imread(fn)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)corners = cv2.findChessboardCorners(gray, CORNER_NUM, None)c = corners[1].flatten().reshape(-1,2)img[where(img < 50)] = 50for cc in c:cv2.circle(img, tuple(cc.astype(int32)), 4, (255,0,0), 3)return img, mean(c, axis=0), sum(var(c,axis=0))#------------------------------------------------------------gifpath = '/home/aistudio/GIF'
if not os.path.isdir(gifpath):os.makedirs(gifpath)
gifdim = os.listdir(gifpath)
for f in gifdim:fn = os.path.join(gifpath, f)if os.path.isfile(fn):os.remove(fn)centerall = []
vdim = []
for id,f in tqdm(enumerate(filedim)):img,c,v=img2Corners(f)centerall.append(c)vdim.append(v)plt.clf()plt.figure(figsize=(10,15))plt.imshow(img)savefile = os.path.join(gifpath, '%03d.jpg'%id)plt.savefig(savefile)#------------------------------------------------------------
'''
xdim = []
ydim = []
for c in centerall:xdim.append(c[0])ydim.append(c[1])plt.clf()
plt.figure(figsize=(10,6))
plt.plot(xdim, ydim)
plt.xlabel("n")
plt.ylabel("value")
plt.grid(True)
plt.tight_layout()
plt.savefig('/home/aistudio/stdout.jpg')
plt.show()'''
#------------------------------------------------------------printt(std(sqrt(vdim)):)plt.clf()
plt.figure(figsize=(10,6))
#plt.hist(sqrt(vdim))
plt.plot(sqrt(vdim))
plt.xlabel("n")
plt.ylabel("R")
plt.grid(True)
plt.tight_layout()
plt.savefig('/home/aistudio/stdout.jpg')
plt.show()#------------------------------------------------------------
# END OF FILE : CHESSB.PY
#============================================================
获取棋盘格与标准模板在扫描仪上不同位置图片相关推荐
- js实现截取网页上特定位置的图片打印或保存
js实现截取网页上特定位置的图片打印或保存 一.实现思路 具体思路是创建一个宽和高都是100%的canvas,使其能够覆盖整个页面,然后根据所要截取的图片起始位置相对于canvas的位置(因为是1 ...
- tcs标准编写软件_【公益培训】知你所需 | 标准编写格式及TCS模板应用线上公益培训...
企业标准编写的水平及TCS工具使用的能力是实施企业标准化工作的基础.TCS标准编写软件是辅助标准编写的工具性软件,方便标准编写人员快捷准确的编写标准草案,有效提升标准供给质量. 为贯彻落实疫情防控和助 ...
- 蓝桥杯算法竞赛系列第0章——蓝桥必考点及标准模板库STL(上)(万字博文,建议抱走)
欢迎来到:遇见蓝桥遇见你,不负代码不负卿! 目录 一.蓝桥必考点剖析 二.什么是STL 三.vector的常见用法详解 1.vector的定义 2.vector容器内元素的访问 (1).通过下标访 ...
- STL学习系列一:STL(标准模板库)理论基础
STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称.现然主要出现在C++中,但在被引入C++之前该技术就已经存在了很长的一段时间. STL的从广 ...
- stl标准模板库_如何在C ++ STL(标准模板库)中使用Pair
stl标准模板库 In this article, we'll take a look at using pair in C++ Standard Template Library (STL). 在本 ...
- 《C++ Primer Plus》学习笔记-string类和标准模板库
第16章 string类和标准模板库(本书附录G有详细介绍) 16.1 string类 string类是由头文件string支持的. string类位于命名空间std中. ctor标识是传统C++中构 ...
- C++ STL 标准模板库介绍与入门
目录 1.概述 1.1.C++ 标准库 1.2.Boost库 2.STL 版本 2.1.HP 原始版本 2.2.P. J. 实现版本 2.3.RW 实现版本 2.4.SGI 实现版本 2.5.STLp ...
- 【跟学C++】C++STL标准模板库——算法详细整理(下)(Study18)
文章目录 1.简介 2.STL算法分类及常用函数 2.2.变序算法(二) 2.2.1 替换算法(2个) 2.2.2 排序算法(6个) 2.2.3 分区算法(4个) 2.2.4 可用于排序容器的算法(3 ...
- C++入门到精通 ——第七章 STL标准模板库大局观
七.STL标准模板库大局观 Author: XFFer_ 先分享一本 <C++ 标准库 第二版> ,望在STL的道路上从入门到放弃!(开玩笑的啦,愈行愈远~) 链接: https://pa ...
- C++标准模板库(STL)的容器的底层实现
STL(Standard Template Library),即标准模板库,是一个具有工业强度的,高效的C++程序库. 以上图片来自 C++中的容器分为顺序容器和关联容器,所有容器都是类模板 使用模板 ...
最新文章
- 欧盟「人脑计划」​最新进展:新算法模拟生物进化,为大脑如何工作提供新见解...
- mac如何修改php.ini,mac 如何修改php.ini
- arp_ignore和arp_announce内核参数
- numpy append
- Extjs遇到的一些问题
- mysql 写磁盘_图解MySQL | [原理解析] MySQL insert 语句的磁盘写入之旅
- 常见的攻击手段及其防御方式
- Python基础(八)--迭代,生成器,装饰器与元类
- 互联网推送服务原理:长连接+心跳机制(MQTT协议)
- 学习老男孩linux全程班决心书
- 史上最权威的 Activiti 框架学习
- linux基础命令游戏,LINUX-基础命令(三)
- 伦茨8400变频器面板按键说明_国产变频器按键的各个功能
- HDFS原理(超详解)
- Ubuntu18.04完全美化及常用软件安装 |QQ|TIM|微信|坚果云|备份
- CS61a-2020fall学习笔记
- Photoshop平面设计:网页设计之论摹仿和抄袭——xiame.com
- 网络分析优化顶点覆盖Vertex Cover算法初探
- 同一台计算机同时安装多个打印机,r230驱动-同一台电脑可不可以装两台同品牌同型号的打印 – 手机爱问...
- AopAutoConfiguration matched的异常
热门文章
- 2018CVPR:Non-local Neural Networks(自注意力机制捕获远程依赖)
- 验证集精度高于训练集精度的原因分析
- 32位win10服务器系统,32位win10原版
- 华硕服务器主板型号命名规则,华硕ROG系列主板命名规则详解_华硕 Maximus V Formula_主板评测-中关村在线...
- 使用IP-guard补丁分发批处理脚本实现分发补丁
- Modbus的CRC校验算法
- 【C语言】【笔记】ASCII码值表;常用转义字符表
- 【OpenCV】 车牌识别检测
- 万字详解OpenDRIVE文件
- VGG-16网络结构