博文: https://blog.csdn.net/lynnandwei/article/details/7741640
最近看到Leptonica,GIMP等,当时的感觉就是惊叹。这种惊叹就像以前我06年刚了解到OpenCV,10年刚了解到ROS时的感觉。但是Leptonica存在很久了,只是由于它很低调,一直没有认真的来了解它。
Leptonica 是一个面向教学的开源网站,广泛的应用于图像处理和图像分析的应用中。说它广泛应用,可不是虚夸一句,在很多linux操作系统中,都自带了它的套件。但是在使用它的时候,由于它设计精巧,加上它用的一些名称,和我们学过的并不一样,如常用的Bitblt位图操作被称为Rasterop,而腐蚀,膨胀等形态学操作不是独立的函数,而是由pixMorphSequence加上不同的参数来完成。还譬如说在对一张图设置对应的mask,并将mask覆盖的点置为0,对于32位的图像,pixSetMasked(pixc, pixt2, 0xffffffff);但是如果是16位,则赋值就是0xffff。你对32位的图像赋值0xffff也可以,但是结果就大相径庭了。所有刚开始在找一些基本操作时会很不习惯。
总的来说,操作有如下几部分:位图操作, 仿射变换,形态学操作,卷积,联通区域填充和图像转换,像素掩膜(mask)增强等操作。
1. Rasterops Leptonica实现了一个干净快速的rasterops。底层代码实现在 roplow.c and ropiplow.c, 而且在rop.c中给出了一个简单的Pix图像数据结构的接口。
2. Binary morphology二元形态学通过两种方式来实现。1对于整个图像应用任意结构元素(Sels)(在OpenCV中是elements )来进行位图操作。2对特殊的Sels进行Destination word accumulation (dwa)(目标字积累)代码是自动生成的,例如,fmorphgen.1.c和 fmorphgenlow.1.c.的代码就是由运行prog/fmorphautogen.c.自动生成的。可以比较dwa和整图位图操作的结果prog/fmorphauto_reg.c.
第二中方法比第一种要快,因此我们致力对所有Sels进行支持,但我们还是支持了两种不同的边界腐蚀。
同样,dwa代码针对一般的hit-miss 变换 也能通过Hit-miss Sels数组自动生成 当prog/fhmtautogen.c编译运行时,它在fhmtgen.1.c和fhmtgenlow.1.c中产生dwa的c代码。这些文件可以被编译成库或者在其他程序中编译。morphseq.c中提供了一些带着简单参数的函数来执行一系列形态学运算(加上二进制降级和复制扩张)结构元素是通过morph.h中定义的简单的Sel结构内容来表示。我们提供了至少7种方法在sell.c中来生成Sels,并可以在selgen.c中找到一些简单的方法来为模式查找生成hit-miss Sels。
在使用中,最常见的形态学Sels是n x m维的独立bricks结构。因此,我们对Brick Sels通过二值处理(rasterops和dwa)提供可分离(独立)的形态学操作。Morphseq.c针对一系列二值化操作和灰度的形态学操作提供相应的解析器。使用解析器的优势在于不需要创建和释放Sels,也不需要任何中间图像保存。
我们还针对二值图像给出了rasterops 和dwa的composable separable brick函数。 它们将线性操作分解到一系列不同尺度上的两个操作,简化操作是根据到一些分解因子的集合,而不是根据未分解的因子的产物。(These decompose each of the linear operations into a sequence of two operations at different scales, reducing the operation count to a sum of decomposition factors, rather than the (un-decomposed) product of factors.....这句翻译还需要斟酌)一如既往,解析器提供了一系列这样的操作。
3. 灰度形态学和秩排序滤波器 Grayscale morphology and rank order filters
Brick Sels可以分成水平单元和垂直单元,我们使用van Herk/Gil-Werman 算法使得单位时间内计算独立于Sels的大小。实现了tophat和hdome,代码在graymorphlow.c 中。
也对brick filter提供了灰度秩排序滤波器 。秩排序滤波器是从灰度形态学中衍生而来, 选择具有排名值的像素(而不是最小或最大)。
颜色的秩排序滤波器适用于灰度级操作独立于(R,G,B)组件。
4. 图像缩放
leptonica针对图像缩放提供许多简单和相对有效 的算法实现。这里列出了其中一些;可以从代码或网页上查找所有的实现。
灰度和彩色图像缩放使用:
- 采样
- 低通滤波抽样,
- 区域映射 (个人发现用得非常多)
- 线性插值
缩放操作中反锯齿采样,面积映射, 线性插值适用于2,4和8 bpp的灰色图像, 24 bpp的全RGB色彩,2,4和8 BPP的彩色映射 (BPP ==位/像素)。
缩放操作中简单抽样 可以在1,2,4,8,16和32 bpp的图像中使用。线性插值速度较慢,但给更好的效果,特别是为upsampling。
中度降采样,得到最好的结果是area mapping scaling。高度的降采样,无论是面积映射area mapping 或反锯齿取样antialias sampling (lowpass filter followed by sampling) 都有良好的效果。也提供了Fast area map 快速面型映射算法以2的指数级降采样。重采样后可选锐化后能通过平衡锐化的边界来减少视觉效果改善外观。
灰度和彩色图像的快速分析,有整数级降采样结合像素深度减少时非常有用。 RGB彩色图像由此可以转换为低分辨率的 灰度和二进制图像。
对于二进制图像缩放,目的像素可以从最接近的相应源像素中选择。对于特殊情况下以2的指数级减少的缩放,低通秩排序滤波器 具有优势。各向同性的的整数扩张可以通过像素复制来完成。
我们还提供二进制图像的2X,3X,4X,6X,8X和16X的灰度缩放 ,以得到高品质的减灰度图像。 这些都整合在scale-to-gray函数中。 相反,我们也提供灰度图像2倍和4倍的scale-to-binary ,通过阈值或抖动,采用在灰度 光栅线缓冲器上线性插值。
还给出了没有缩放的图像深度转换操作, 如对1 bpp的拆包操作到灰度图像,通过 阈值和抖动操作从灰度图像到1,2和4 BPP图像。
5。图片剪切和旋转(仿射,投影...)
图像剪切通过rasterops和线性插值来实现。
RasterOp实现方法执行速度更快,图像深度没有限制。我们提供了in place和从源图到目标图方式的任意点的横向和纵向剪切。
插值剪切只适用于8 bpp和32 bpp的图像, 给出了一个平滑后的结果。剪切可用于 旋转的快速实现。
一般的图像旋转子有三种不同的类型:
a 通过面积映射 area mapping 进行灰度旋转。
- pixRotateAM() for 8 bit gray and 24 bit color, about center
- pixRotateAMCorner() for 8 bit gray, about image UL corner
- pixRotateAMColorFast() for faster 24 bit color, about center
b. 任意bit任意深度图像的旋转,通过两到三个剪切动作来完成。这样的旋转可以对任意点旋转。也可以是从源图像到目的图像的或者in place的操作。例如
- pixRotateShear()
- pixRotateShearIP()
c. 通过抽样旋转。可用于任意深度图像,任意点进行。保留Colormaps 。
图像映射旋转比较慢,但是更精确。因为每个新的像素点通过对原图中四个
相邻像素平均而得到,这种方法有时 也被称为“抗锯齿”。快速的颜色区域映射旋转算法也提供了。代码是在rotateamlow.c。
剪切旋转算法速度更快,能在任意像素深度图像上工作 ,但他们只是移动周围的像素, 没有做任何平均。 pixRotateShearIP()就在图像上in-place的操作。 我们还对任意深度图像提供正交的旋转子(90,180,270度,左,右 翻转和顶底翻转)。并提供了仿射,投影和双线性 转换的实现,包括采样算法(速度优先)和插值算法的(抗锯齿)。