数字图像处理是工程领域中极为重要的问题之一。本文不打算描述其广泛的应用,因为这些应用可以在其他地方找到。本文旨在探讨如何将图像处理技术集成到工程框架中,以及这样做所带来的多种优势。例如,通过照片确定三维物体的6D位置,最新的任务要求对三维形状的二维图像轮廓进行处理。文章开头的图片就是这样一个通过图像处理获得的轮廓。
许多图像处理方法基于以下原理:图像像素的颜色是计算的结果,计算的输入数据是源图像的颜色。存在两种类型的处理。第一种是本地处理,目标图像中一个像素的颜色仅依赖于源图像中相应像素的颜色。第二种是非本地处理,目标像素的颜色依赖于邻近的源像素。下面将分别考虑这两种类型的处理。
本地处理的方案如下所示:下面的图片描述了两个图像。"Lady Rose"是源图像,"Lady Blue"是目标图像。其他的方块是数学变换。下面的图片展示了两位女士:
// 示例代码,展示如何进行本地处理
Image sourceImage = loadImage("ladyRose.jpg");
Image destinationImage = createImage(sourceImage.width, sourceImage.height);
for (int x = 0; x < sourceImage.width; x++) {
for (int y = 0; y < sourceImage.height; y++) {
color pixelColor = sourceImage.get(x, y);
destinationImage.set(x, y, pixelColor);
}
}
根据软件功能,变换的结果不仅依赖于源图像像素的颜色,还依赖于像素的坐标。因此,两位女士的脸部和手部颜色是相同的。
非本地处理比本地处理更具科学性。例如,它用于面部检测。使用它来通过照片确定三维物体的6D位置。现在,将介绍Sobel梯度方法。方案如下所示:
// 示例代码,展示如何进行非本地处理
PImage sourceImage = loadImage("initial.jpg");
PImage uncoloredImage = new PImage(sourceImage.width, sourceImage.height);
for (int x = 1; x < sourceImage.width-1; x++) {
for (int y = 1; y < sourceImage.height-1; y++) {
float gx = (sourceImage.get(x-1, y) >> 16 & 0xFF) - (sourceImage.get(x+1, y) >> 16 & 0xFF);
float gy = (sourceImage.get(x, y-1) >> 16 & 0xFF) - (sourceImage.get(x, y+1) >> 16 & 0xFF);
int gradient = (int)sqrt(gx * gx + gy * gy);
uncoloredImage.set(x, y, color(gradient, gradient, gradient));
}
}
该方案包含从"Initial"到"Uncolored"再到"Grad picture"的图像级联变换。下面的三张图片展示了这些变换:
本节与图像处理没有直接关系。有时需要对物理现象进行2D可视化。框架中的数据使能够做到这一点。下面的图片是与光纤相关的一个现象的表示:
框架的真正目的不仅仅是将图像处理应用于工程任务,而是纯粹的图像处理。让考虑这个领域的典型任务。假设有一张脏乱的图表图片,希望建立数学依赖性。这种情况在下面的图片中展示。
// 示例代码,展示如何确定数学依赖性
Image sourceImage = loadImage("dirtyGraph.jpg");
Image transformedImage = processImage(sourceImage);
List xCoordinates = selectBlackPoints(transformedImage, true);
List yCoordinates = selectBlackPoints(transformedImage, false);
Function graphApproximation = fitLine(xCoordinates, yCoordinates);
"Source"图片是数学依赖性的坏图像。"Transform"是图像变换的结果。"Selection"组件从"Transform"图像中进行两次选择。第一次选择是x坐标的黑色点集合,第二次选择是y坐标的集合。使用回归(见第2部分)组件"Processor",处理这些选择,并用分段线性函数近似图形。
让考虑一个更复杂的例子。假设有以下示波器照片:
// 示例代码,展示如何处理示波器图像
Image oscillogramImage = loadImage("oscillogram.jpg");
Image processedImage = applyLocalAndNonlocalProcessing(oscillogramImage);
List sineFunctions = extractSineFunctions(processedImage);
希望获得正弦图的数学公式,但照片并不理想。此外,坐标轴并不完全水平和垂直。首先,应该应用本地和非本地处理。下面的图片展示了简要的结果:
如果有几组三维物体的照片,可以确定其6D位置。在这个例子中,这个问题是这样解决的。从照片和虚拟相机中,获得物体的轮廓,如下所示:
// 示例代码,展示如何进行视频导航
List objectImages = loadObjectImages();
List contours = extractContours(objectImages);
PVector matchedContour = perform6DMotion(contours);