1、默认采用ISO-8859-1字符编码,为何能处理中文?
答:ISO-8859-1即“标准码”,也称Latin-1,收录的字符除ASCII收录的字符外,还包括西欧语言、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号。欧元符号出现的比较晚,没有被收录在ISO-8859-1当中。ISO-8859-1编码是单字节编码,向下兼容ASCII,其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致,0x80-0x9F之间是控制字符,0xA0-0xFF之间是文字符号。这是唯一单字节且能表示多种语言种类的字集编码,它是在有限的空间中实现更丰富的内涵的首选字集编码。即相当于采用什么样的文字去描述内容。在BYTE mode下,所有的字符串都要先转换成ISO-8859-1或UTF-8。然后再进行编码。
2、Shift_JIS是什么编码模式?
答:是一个日本电脑系统常用的编码表。
3、ALPHANUMERIC是字母数字模式,是如何使用的?
答:其对应ALPHANUMERIC_TABLE,该表提供了QR码在字母数字模式下支持的字符的参考。具体定义如下:
代码后面是44个ALPHANUMERIC mode所认可的字符及其对应的数值表示。
原始表定义在JISX0510:2004 (p.19)的表五,JISX0510:2004是日本工业调查会发布的关于二维码编码基本标准则。
附:通过测试,纯数字会选择Mode::NUMERIC(=1,0001),数字、大写字母及有限的几个符号会选择Mode::ALPHANUMERIC(=2,0010),小写字母及其他则为Mode::BYTE(=4,0100)。1、2、4为指示值,用4bits表示。
如果是NUMERIC类型的,即数字,则数字串按三位拆分,如果数字的个数不是3的倍数,那么,最后剩下的1或2位数会被转成4或7bits,其它的每3位数字会被编成10,12,14bits,编成多长还要看二维码的尺寸(如下表)。
即对每个文字如何进行位拆分。
3-1、当前源码支持的最高版本是多少?
从以上代码可知当前最大支持到ver-7 H级。
当编码模式与版本定了后,要生成字符数指标器值,这个值放在模式指标值后面。
appendLengthInfo函数就是做这件事的。
以下是对应版本、编码模式所对应的numBits的大小。
appendBytes函数按照mode将字节编码到位bits中去。
4、qDebug() << __FUNCTION__;的作用?
答:可打印出该行所在的函数名称。
5、BitArray类解析
5.1、static const int bitsPerWord = std::numeric_limits<unsigned int>::digits;
答:C++11支持static const int型在类内初始化,而static int或是static const float则不可以实始化,等式右边是相应类型的最大基数(数据类型在不损失精度的情况下可以表示的基数位数)。
5.2、QSharedPointer类型
答:Qt中的智能指针,与 C++中的std::shared_ptr(编译时需要添加-fpermissive,否则会出现:error: there are no arguments to '_M_get_pointer' that depend on a template parameter, so a declaration of '_M_get_pointer' must be available [-fpermissive])其作用是一样。
5.3、BitArray定义的几个对象及关键对外接口
sizeof测试为12字节。
6、如何理解解码格式?
答:比如DecoderFormat_EAN_13 = 1 << 8,这实际就是256 。DecoderFormat_QR_CODE = 1 << 12,即4096。最后赋值给DecodeHintType EAN_13_HINT和DecodeHintType QR_CODE_HINT,DecodeHintType就是个无符号的整型类型,在class DecodeHints中使用。
7、是否支持图像旋转?
答:貌似不支持!
8、当前我生成的着色二维码图像类型为什么?如何灰度化?
答:QImage::Format_RGB32,即The image is stored using a 32-bit RGB format (0xffRRGGBB).
库中采用Gray = 0.2126×Red + 0.7152×Green + 0.0722×Blue公式进行灰度化处理。
9、R_TO_GREYSCALE[256]、G_TO_GREYSCALE[256]、B_TO_GREYSCALE[256]中的数值是如何来的?
答:
10、byte & 0xff有什么作用?
答:将byte从(-128 至 127)转化成 int(转化后的数值范围: 0 至 255)。其实就是1个byte有两种表示方法,我们既可以用-128 - 127这段范围来表示一个字节,也可以用 0 - 255这个范围的数来表示一个字节。
11、反向亮度源时,为什么要用0XFF减byte?
答:
12、什么是基于直方图的图像全局二值化算法?QZXing中使用了哪种直方图算法?
答: 图像二值化的目的是最大限度的将图象中感兴趣的部分保留下来,在很多情况下,也是进行图像分析、特征提取与模式识别之前的必要的图像预处理过程。这个看似简单的问题,在过去的四十年里受到国内外学者的广泛关注,产生了数以百计的阈值选取方法,但如同其他图像分割算法一样,没有一个现有方法对各种各样的图像都能得到令人满意的结果。
在这些庞大的分类方法中,基于直方图的全局二值算法占有了绝对的市场份额,这些算法都从不同的科学层次提出了各自的实施方案,并且这类方法都有着一些共同的特点:简单、算法容易实现、执行速度快。
所谓图像的灰度直方图是在将图像进行灰度处理后,计算灰度值的分布。也就是每个灰度值在灰度图像中有多少个点。一般情况下,图像灰度值的取值范围为0~255,所以灰度直方图是一个有256个元素的数组。阈值分割就是找到一个合适阈值,对灰度图像进行处理。大于阈值的设置为255,小于阈值的设置为0。也可以根据需要设为其他数值。这样处理灰度图像,可以将前景与背景做一个区分。
这类方法主要有:灰度平局值值法、百分比阈值(P-Tile法)、基于谷底最小值的阈值、基于双峰平均值的阈值、迭代最佳阈值、OSTU大律法、一维最大熵、力矩保持法 、基于模糊集理论的阈值、Kittler最小错误分类法、ISODATA(也叫做intermeans法)、Shanbhag 法、Yen法。
QZXing源码中采用基于双峰平均值的阀值来处理的。算法函数原型如下:
int GlobalHistogramBinarizer::estimateBlackPoint(QSharedPointer<std::vector<int>> const& buckets);
13、如何改造现有的代码,实现对着色二维码识别?
答:
14、解码为什么要分成二个阶段?
答:第一阶段是处理最理想的情况,第二阶段是处理不太理想的情况,需要对源图像作旋转、剪裁等操作后再解码。
第一阶段:默认情况下调用QRCodeReader->decode解码函数,该函数调用lobalHistogramBinarizer::getBlackMatrix(),在这个函数中有计算直方图的功能,其实现是通过从图像中采样四行来快速,其效率高于从对角线采样。进而用基于双峰平均值的阀值算法计算出灰度值。通过比对灰度值将位图矩阵灰化处理,在应用上是保存有用信息,实际中是把不同着色点以黑白两色来替换。
15、灰度化中估算黑点算法是如何实现的?
答:首先分析采样点的类型,QSharedPointer<std::vector<int>> const& buckets。QSharedPointer是Qt中的一个智能指针,其指向一个标准矢量容器,容器中的数据类型为int型,这个int型的值表示的是什么呢?是何时存放的呢?这是我们接着所关注的问题,
对位图进行封装,形成CameraImageWrapper类对象,用智能指针QSharedPointer指向,CameraImageWrapper派生自LuminanceSource抽象类,其成员变量是width、height,提供getRow、getMatrix纯虚函数及crop、invert、rotateCounterClockwise、rotateCounterClockwise45虚函数。CameraImageWrapper类中有Factory、getOriginalImage、getDelegate、getRow、getMatrix、crop、invert、rotateCounterClockwise、gray、getRowP、getMatrixP、updateImageAsGrayscale等函数,并有几个重要的成员变量。
QSharedPointer<GreyscaleLuminanceSource> delegate;
QSharedPointer<std::vector<QSharedPointer<std::vector<zxing::byte>>>> imageBytesPerRow;
QSharedPointer<std::vector<zxing::byte>> imageBytes;
static const zxing::byte B_TO_GREYSCALE[256];
static const zxing::byte G_TO_GREYSCALE[256];
static const zxing::byte R_TO_GREYSCALE[256];
getMatrix函数返回的是QSharedPointer<std::vector<zxing::byte>>类型。getRow与它相同。
其构造函数中调用了updateImageAsGrayscale函数,生成300*250的像素点的字节,保存在上述imageBytes成员变量中。其行数250保存在imageBytesPerRow中。(即每个像素用一个zxing::byte字节来保存)
再将CameraImageWrapper对象封装成GlobalHistogramBinarizer对象,其是Binarizer抽象类的派生类。Binarizer类中有QSharedPointer<LuminanceSource> source_、Binarizer(QSharedPointer<LuminanceSource> source)。纯虚函数getBlackRow、getBlackMatrix。常函数getLuminanceSource、getWidth、getHeight()。GlobalHistogramBinarizer类中有QSharedPointer<std::vector<zxing::byte>> luminances、 QSharedPointer<std::vector<int>> buckets。GlobalHistogramBinarizer(QSharedPointer<LuminanceSource> source)。getBlackRow、getBlackMatrix()、estimateBlackPoint、createBinarizer等函数。
再将GlobalHistogramBinarizer对象封装成BinaryBitmap对象bb,对这个bb进行解码处理。
BinaryBitmap类中有QSharedPointer<Binarizer> binarizer_成员。getBlackRow、getBlackMatrix、getLuminanceSource、getWidth、getHeight、rotateCounterClockwise、rotateCounterClockwise45、crop函数。
调用getBlackMatrix函数,最终又回到GlobalHistogramBinarizer::getBlackMatrix的调用。
16、void CameraImageWrapper::updateImageAsGrayscale(const QImage &origin)灰度化函数处理原理是什么?
答:
17、四行采样法快速生成直方图的原理是什么?
答:Quickly calculates the histogram by sampling four rows from the image. This proved to be more robust on the blackbox tests than sampling a diagonal as we used to do.
灰度直方图,横坐标表示灰度,纵坐标表示该灰度在图像中出现的频次。其能提供有效的阀值。例如:如果感兴趣的物体在其内部具有均匀一致的灰度值并分布在具有另一个灰度值的均匀背景上,直方图就会呈现出容易辨认的 “双峰”或 “多峰”形,此时根据直方图确定图像分割的阈值就是很好的方法。即检测直方图曲线的波谷和波峰,并把波谷对应的像素灰度值设置成阈值。
18、imageBytes与buckets存在什么关系?
答:
imageBytes是CameraImageWrapper类中的成员变量,定义如下:
其保存来自于图片的每个像素点的灰度化后的值,空间大小为300*250。
buckets是GlobalHistogramBinarizer类中的成员变量,定义如下:
其保存32个指向std::vector<int>类型的智能指针。
两者通过下述代码关联在一起:
19、二维码纠错算法原理是什么?
答:
二、算法
1、基于采样的直方图;
简介:图像匹配指在已知目标基准图的子图集合中,寻找与实时图像最相似的子图,以达到目标识别与定位目的的图像技术。图像匹配的方法有:基于图像灰度相关法、基于图像特征法、基于神经网络相关的人工智能法(仍在完善中......)。
基于图像灰度的匹配算法简单,匹配准确度高,主要用空间域的一维或二维滑动模版进行图像匹配,不同的算法区别主要体现在模版及相关准则的选择方面,但计算量大,不利于实时处理,对灰度变化、旋转、形变以及遮挡等比较敏感。
基于图像特征法计算量相对较小,对灰度变化、形变及遮挡有较好的适应性,通过在原始图中提取点、线、区域等显著特征作为匹配基元,进而用于特征匹配,但是匹配精度不高。
人们通常把基于图像灰度的匹配算法称相关匹配算法。相关匹配算法又分为两类:一类强调景物之间的差别程度如平方差法(SD)和平均绝对差值法(MAD)等;另一类强调景物之间的相似程度,主要算法又分成两类,一是积相关匹配法,二是相关系数法。NCC是归一化互相关系数法,英文全称Normalized Cross Correlation。
2.1、NCC原理:
假设两幅进行匹配计算的图像中的小图像为g,大小为m×n,大图像为S,大小为M×N.用Sx,y表示S中以(x,y)为左上角点与g大小相同的子块。利用相关系数公式计算实时图和基准图之间的相关系数,得到相关系数矩阵ρ(x,y),通过对相关系数矩阵的分析,判断两幅图像是否相关。
ρ(x,y)的定义为:
分子为Sx,y和g的协方差,分母Dx,y为Sx,y的方差,D为g的方差。