一提到特征工程,我们马上就会想到表格数据。但我们也可以获得图像数据的特征并提取图像最重要的方面。这样做可以更容易地找到数据和目标变量之间的映射。这使得使用更少的数据和训练更小的模型成为可能。较小的模型减少了进行预测所需的时间。这在部署到边缘设备时特别有用。另一个好处是可以更加确定模型用于进行这些预测的内容。本文将介绍使用Python进行图像特征工程的一些方法:CroppingGrayscallingSelectingRGBchannelsIntensitythresholdsEdgedetectionColorfilters(提取给定颜色范围内的像素)我们将在自动驾驶汽车上进行演示。如下图所示,轨道图像训练模型。然后该模型将用于进行预测以引导汽车。我们将在本文末尾讨论图像数据特征工程的局限性。特征工程和增强在深入研究之前,有必要先讨论一下图像增强。这种方法的目标类似于特征工程。但它的做法不同。什么是数据增强?数据扩充是指我们使用代码系统地或随机地更改数据。对于图像,这包括翻转、调整颜色和添加随机噪声等方法。这些方法允许我们人为地引入噪声并增加数据集的大小。在生产中,模型需要在不同的条件下执行。这些条件由照明、相机角度、房间颜色或背景中的物体等变量决定。数据扩充的目标是创建一个对这些条件的变化具有鲁棒性的模型。它通过添加模拟真实世界条件的噪声来做到这一点。例如,改变图像的亮度类似于在一天中的不同时间收集数据。增强还允许我们通过增加数据集的大小来训练更复杂的架构。或者它有助于模型参数收敛。图像数据特征工程特征工程的目标类似于增强,即创建更健壮的模型。但不同之处在于它消除了准确预测不需要的任何噪音。也就是说,删除了在不同条件下发生变化的变量(这与增广正好相反)。通过提取图像的最重要部分来简化问题。这允许更简单的模型架构。我们可以使用较小的数据集来找到输入和目标之间的映射。另一个重要的区别是这些方法在生产中的处理方式。您的模型不会对增强图像进行预测。但是对于特征工程,模型将需要对它所训练的相同特征进行预测。这意味着必须可以在生产环境中进行相同的特征工程。使用Python进行图像特征工程下面进入正题,开始特征工程操作。我们有一些标准包(第2-3行)。Glob用于处理文件路径(第5行)。我们还有一些用于处理图像的包(第7-8行)。importnumpyasnpimportmatplotlib.pyplotaspltimportglobfromPILimportImageimportcv2我们将在此处使用用于为自动驾驶汽车提供方向路径的图像。您可以在Kaggle上找到这些示例。使用以下代码加载其中一张图像。首先加载所有图像的文件路径(第2-3行)。然后加载(第8行)并在第一个路径上显示图像(第9行)。这个图像可以在图1中看到。10,10))#Displayimageimg=Image.open(img_paths[0])plt.imshow(img)Cropping对图像进行裁剪,去除不需要的外部区域,目的是只去除图像不需要的部分用于预测。对于自动驾驶汽车,可以从背景中移除像素。加载图像(第2行)。然后将此图像转换为数组(第5行)。这个数组的大小是224x224x3。图像的高度和宽度都是224个像素,每个像素都有一个RGB通道。为了裁剪图像,我们只选择y轴上位置25以上的像素(第8行)。结果如图2所示。#Loadimageimg=Image.open(img_paths[609])#Coverttoarrayimg=np.array(img)#Simplecropcrop_img=img[25:,]ifrequiredtomaintainaspect比率。通过将不需要的像素变黑(第3行)可以实现类似的结果。通过裁剪,我们删除了不必要的像素,从而防止模型过度拟合训练数据。例如,背景中的椅子可能会出现在所有左转弯处。该模型有可能将这些与左转预测联系起来。上面的图像可以进一步处理,例如在不删除任何轨道的情况下裁剪图像的左侧。但在下图中,我们要删除重要的轨道部分。crop_img=np.array(img)crop_img[:25,]=[0,0,0]crop_img[:,:40]=[0,0,0]为什么要这样做?这又回到了特征工程需要在生产中发生的问题。您不知道什么时候会向模型显示什么图像。这意味着对所有图像应用相同的裁剪函数,确保它永远不会删除图像的重要部分,这是不可能的,因此我们需要模拟这种情况。Grayscalegray_img=cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)灰度是通过捕捉图像中的颜色强度来实现的。它通过对RGB通道进行加权平均来实现。我们使用这个公式:Y=0.299r+0.587g+0.114*b如果我们使用所有RGB通道,它将包含150,528个值(2242243)。对于灰度图像,我们现在只有50,176个值(224*224)。更简单的输入意味着更少的数据和更简单的模型。在RGB通道中,一个通道可能更重要。我们可以不用灰度,直接只用这个通道。例如下面,我们选择R(第6行)、G(第7行)和B(第8行)通道。每个生成的数组的尺寸为224x224。您可以在图6中看到相应的图像。#Loadimageimg=Image.open(img_paths[700])img=np.array(img)#Getrgbchannelsr_img=img[:,:,0]g_img=img[:,:,1]b_img=img[:,:,2]这里也可以使用channel_filter函数。通道参数(c)的值为0、1或2,具体取决于您想要的通道。但有一件事,不同的python包将以不同的顺序加载频道。我们在这里使用的PIL是RGB。如果使用cv2.imread()加载图像,通道将按BGR顺序排序。defchannel_filter(img,c=0):"""Returnsgivenchannelfromimagepixels"""img=np.array(img)c_img=img[:,:,c]returnc_img使用灰度或RGB通道选择,你需要考虑是否要从图像中删除重要信息。但对于本文中的轨道示例,轨道是橙色的,所以没问题,轨道的颜色有助于将其与图像的其余部分区分开来。这在实际应用中也需要考虑。强度阈值使用灰度,每个像素将具有0到255之间的值。我们可以通过将其转换为二进制值来进一步简化输入。如果灰度值高于阈值,则像素值为1,否则为0。我们称此为强度阈值。下面的函数用于应用此阈值。首先对图像进行灰度化(第5行)。如果像素高于阈值,则将其设置为1000(第8行)。如果像素值低于阈值,它将被设置为0(第9行)。最后,将再次缩放所有像素,使它们的值为0或1(第11行)。自动驾驶汽车项目的一部分是为了避开障碍物。在图7中,您可以看到如何应用强度阈值函数,我们可以从图像中分离出这个黑色罐头障碍物。这里的截止值可以看作是一个超参数。更大的截断意味着我们包含更少的背景噪音。但缺点是我们的捕获范围较小。边缘检测如果要分离轨道,可以使用更精细的边缘检测方法。这是一种用于检测图像边缘的多阶段算法。在这里,我们使用cv2.Canny()函数应用该算法。其中threshold1和threshold2是迟滞过程参数。这是边缘检测算法的最后一次确定哪些线是真正的边缘。#Applycannyedgedetectionedge_img=cv2.Canny(img,threshold1=50,threshold2=80)就像强度阈值一样,我们得到一个二进制图-边缘为白色,其他为黑色。这条痕迹现在更容易与图像的其余部分区分开来。但是可以看出背景中的边缘也被检测到了。如果我们使用像素颜色来隔离轨迹,颜色过滤器可能会有更好的结果。使用下面的pixel_filter函数来执行此操作。cv2.inRange()将图像转换为二值图(第10行)。此函数检查像素是否在较低(第5行)和较高(第6行)列表给出的范围内。具体来说,每个RGB通道必须在其各自的范围内(例如134-t≤R≤194+t)。defpixel_filter(img,t=0):"""过滤范围内的像素"""lower=[134-t,84-t,55-t]upper=[192+t,121+t,101+t]img=np.array(img)orange_thresh=255-cv2.inRange(img,np.array(lower),np.array(upper))returnorange_thresh简单来说,这个函数判断像素颜色是否足够接近轨道的橙色。结果如图9所示。参数t引入了一些灵活性。使用更高的值来捕获更多的轨道,但保留更多的噪声。这是因为背景中的像素也会落在这个范围内。我们从哪里得到下限和上限?那就是我们怎么知道它会落在[134,84,55]和[192,121,101]之间?如果大家有兴趣,我们会在后面的文章中进行讲解。在图10中,您可以看到正在运行的选择器。从多个图像中选择像素并尝试在轨道上的不同位置选择它们。这样我们就可以得到不同条件下的完整像素值。我们总共选择了60种颜色。所有这些都可以在图11中看到。所有这些颜色的RGB通道都存储在列表变量-“颜色”中。最后,我们为每个RGB通道取最小值和最大值。这给出了下限和上限。lower=[min(x[0]forxincolours),min(x[1]forxincolours),min(x[2]forxincolours)]upper=[max(x[0]forxincolours),max(x[1]forxincolours),max(x[2]forxincolours)]特征工程的局限性以上是图像数据的基本特征工程,但你可能认为这些方法不是那么容易使用。这是因为深度学习的一个主要好处是它可以在不需要特征工程的情况下识别复杂的模式。你需要弄清楚图像的哪些方面是重要的,然后编写代码来提取那些方面,这些方面在NeuralWangLuo出现后变得不那么重要了。同样对于某些方法,我们已经看到不可能消除所有噪声。例如,黑色背景中的噪声和对象像素具有相同的值。这些是手动功能的缺陷。但是在处理相对简单的计算机视觉问题时,手动提取特征非常有用。比如在这个无人驾驶汽车里,我们的轨迹永远不会变,物体的颜色永远是一样的,这样既可以加快运算速度,又可以保证准确性。对于更复杂的问题,我们需要更多的数据,或者使用深度学习的方法进行复杂的模式识别。https://avoid.overfit.cn/post/bd8d9a344381437d92d8b2f714359332作者:ConorO'Sullivan
