我在 Octave 中的程序使用神经网络来识别手写数字。问题是,如果颜色改变,它将无法正确识别数字。但如果颜色反转,则预测错误。例如:
上面的图像包含相同的数字和相同的图案。但他们有反转的颜色。
我已经在使用RGB 到灰度转换。如何克服这个问题?有没有比对倒置彩色图像使用单独的训练示例更好的选择?
如果您从图像中提取边缘,您会发现它在这方面基本上是不变的,您的图像的两个版本在转换后看起来几乎相同
下面我展示了当您使用拉普拉斯边缘检测提取边缘时图像的外观,对于“黑底白字”和“白底黑字”图像:
这个想法是在边缘训练你的网络,以获得关于你描述的变化的一些不变性。
以下是一些用于边缘提取的 MATLAB/OCtave 资源:
https://mathworks.com/discovery/edge-detection.html https://octave.sourceforge.io/image/function/edge.html
我已经使用 Python 和 OpenCV 完成了边缘提取edges_image = cv2.Laplacian(original_image, cv2.CV_64F)
。如果我可以修复我的安装,我可能会发布一个 MATLAB/Octave 示例:)
另一种方法是决定您要使用一个版本,假设您已经对网络进行了“白色背景上的黑色文本”变体的训练。
现在,当您输入图像时,首先检测主色/背景是黑色还是白色,然后根据需要进行反转。
为了概括@bakkal 使用边缘的建议,可以提取多种类型的图像特征。这些包括边缘、角落、斑点、脊等。实际上,mathworks 上有一个页面,其中包含一些示例,包括使用HOG 特征(定向梯度直方图)进行数字识别。
这种技术也应该适用于更复杂的图像,因为边缘并不总是最好的特征。使用 matlab 从两个图像中提取 HOG 特征extractHOGFeatures
:
如果您有 Octave,我相信您可以将vlfeat用于 HOG 功能。
要记住的另一件重要事情是您希望所有图像具有相同的大小。我已将您的两个图像的大小调整为 500x500,但这是任意的。
上面生成图片的代码
close all; clear; clc;
% reading in
img1 = rgb2gray(imread('img1.png'));
img2 = rgb2gray(imread('img2.png'));
img_size = [500 500]; %
% all images should have the same size
img1_resized = imresize(img1, img_size);
img2_resized = imresize(img2, img_size);
% extracting features
[hog1, vis1] = extractHOGFeatures(img1_resized);
[hog2, vis2] = extractHOGFeatures(img2_resized);
% plotting
figure(1);
subplot(1, 2, 1);
plot(vis1);
subplot(1, 2, 2);
plot(vis2);
您不必受限于 HOG 功能。还可以快速试用SURF 功能
同样,颜色反转并不重要,因为特征匹配。但是你可以看到 HOG 特征在这里可能是一个更好的选择,因为绘制的 20 个点/blob 并不能真正代表数字 6。在 matlab 中获取上述内容的代码。
% extracting SURF features
points1 = detectSURFFeatures(img1_resized);
points2 = detectSURFFeatures(img2_resized);
% plotting SURF Features
figure(2);
subplot(1, 2, 1);
imshow(img1_resized);
hold on;
plot(points1.selectStrongest(20));
hold off;
subplot(1, 2, 2);
imshow(img2_resized);
hold on;
plot(points2.selectStrongest(20));
hold off;
总而言之,根据问题,您可以选择不同类型的特征。大多数情况下,选择原始像素值并不够好,正如您从自己的经验中看到的那样,除非您有一个包含所有可能情况的非常大的数据集。