在单个图像中检测多个图像

我需要帮助来识别边框并将图像与原始图像进行比较。 我需要指导如何通过处理或matlab或任何初学者来实现这一目标。 例如,看下面的图像。

原始图片:

在此处输入图像描述

多重图像: 更大的图像

您展示的“多重图像”很容易使用简单的图像处理来处理,无需模板匹配 🙂

% read the second image img2 = imread('http://i.stack.imgur.com/zyHuj.jpg'); img2 = im2double(rgb2gray(img2)); % detect coca-cola logos bw = im2bw(img2); % Otsu's thresholding bw = imfill(~bw, 'holes'); % fill holes stats = regionprops(bw, {'Centroid', 'BoundingBox'}); % connected components % show centers and bounding boxes of each connected component centers = vertcat(stats.Centroid); imshow(img2), hold on plot(centers(:,1), centers(:,2), 'LineStyle','none', ... 'Marker','x', 'MarkerSize',20, 'Color','r', 'LineWidth',3) for i=1:numel(stats) rectangle('Position',stats(i).BoundingBox, ... 'EdgeColor','g', 'LineWidth',3) end hold off 

在此处输入图像描述

您可以使用相关方法来定位多个图像:

 file1='http://i.stack.imgur.com/1KyJA.jpg'; file2='http://i.stack.imgur.com/zyHuj.jpg'; It = imread(file1); Ii = imread(file2); It=rgb2gray(It); Ii=rgb2gray(Ii); It=double(It); % template Ii=double(Ii); % image Ii_mean = conv2(Ii,ones(size(It))./numel(It),'same'); It_mean = mean(It(:)); corr_1 = conv2(Ii,rot90(It-It_mean,2),'same')./numel(It); corr_2 = Ii_mean.*sum(It(:)-It_mean); conv_std = sqrt(conv2(Ii.^2,ones(size(It))./numel(It),'same')-Ii_mean.^2); It_std = std(It(:)); S = (corr_1-corr_2)./(conv_std.*It_std); imagesc(abs(S)) 

结果将为您提供具有最大值的位置:

在此处输入图像描述

获取最大值的坐标,并将模板质心放在同一位置,检查模板与匹配图像之间的差异。

我不确定“识别边界”是什么意思,但你总是可以用canny探测器提取边缘:

 bw=edge(It); bw=imfill(bw,'holes'); figure,imshow(bw) 

下面介绍使用Marvin图像处理框架在Java中实现的解决方案。

做法:

  1. “原始图像”中加载,分割和缩放(50×50)徽标。
  2. “多个图像”中加载,分割和缩放(50×50)每个徽标
  3. 对于“多个图像”中的每个徽标,请与“原始图像”中的徽标进行比较。 如果它几乎相同,绘制一个矩形突出显示。

比较方法(内部diff插件):

对于两个徽标中的每个像素,比较每个颜色分量。 如果一个颜色分量的差异高于给定阈值,则考虑该两个徽标的像素不同。 计算不同像素的总数。 如果两个徽标的许多不同像素高于另一个阈值,请将它们视为不同。 重要提示:此方法对旋转和透视变化非常敏感。

由于您的样本( “多图” )只有古柯标识,我冒昧地包含另一个标识以断言算法。

多重图像2

在此处输入图像描述

产量

在此处输入图像描述

在另一个测试中,我还包括另外两个类似的古柯标志。 更改阈值参数可以指定是否需要完全相同的徽标或接受其变体。 在下面的结果中,参数设置为接受徽标变体。

多重图像3

在此处输入图像描述

产量

在此处输入图像描述

源代码

 public class Logos { private MarvinImagePlugin threshold = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.color.thresholding"); private MarvinImagePlugin fill = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.fill.boundaryFill"); private MarvinImagePlugin scale = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.transform.scale"); private MarvinImagePlugin diff = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.difference.differenceColor"); public Logos(){ // 1. Load, segment and scale the object to be found MarvinImage target = segmentTarget(); // 2. Load the image with multiple objects MarvinImage original = MarvinImageIO.loadImage("./res/logos/logos.jpg"); MarvinImage image = original.clone(); // 3. Segment threshold.process(image, image); MarvinImage image2 = new MarvinImage(image.getWidth(), image.getHeight()); fill(image, image2); MarvinImageIO.saveImage(image2, "./res/logos/logos_fill.jpg"); // 4. Filter segments by its their masses LinkedHashSet objects = filterByMass(image2, 10000); int[][] rects = getRects(objects, image2, original); MarvinImage[] subimages = getSubimages(rects, original); // 5. Compare the target object with each object in the other image compare(target, subimages, original, rects); MarvinImageIO.saveImage(original, "./res/logos/logos_out.jpg"); } private void compare(MarvinImage target, MarvinImage[] subimages, MarvinImage original, int[][] rects){ MarvinAttributes attrOut = new MarvinAttributes(); for(int i=0; i objects = filterByMass(image2, 10000); int[][] rects = getRects(objects, image2, target); MarvinImage[] subimages = getSubimages(rects, original); return subimages[0]; } private int[][] getRects(LinkedHashSet objects, MarvinImage mask, MarvinImage original){ List ret = new ArrayList(); for(Integer color:objects){ ret.add(getObjectRect(mask, color)); } return ret.toArray(new int[0][0]); } private MarvinImage[] getSubimages(int[][] rects, MarvinImage original){ List ret = new ArrayList(); for(int[] r:rects){ ret.add(getSubimage(r, original)); } return ret.toArray(new MarvinImage[0]); } private MarvinImage getSubimage(int rect[], MarvinImage original){ MarvinImage img = original.subimage(rect[0], rect[1], rect[2], rect[3]); MarvinImage ret = new MarvinImage(50,50); scale.setAttribute("newWidth", 50); scale.setAttribute("newHeight", 50); scale.process(img, ret); return ret; } private void fill(MarvinImage imageIn, MarvinImage imageOut){ boolean found; int color= 0xFFFF0000; while(true){ found=false; Outerloop: for(int y=0; y filterByMass(MarvinImage image, int mass){ boolean found; HashSet analysed = new HashSet(); LinkedHashSet ret = new LinkedHashSet(); while(true){ found=false; outerLoop: for(int y=0; y= mass){ ret.add(color); } analysed.add(color); found = true; break outerLoop; } } } } if(!found){ break; } } return ret; } private int getMass(MarvinImage image, int color){ int total=0; for(int y=0; y x2){ x2 = x; } if(y1 == -1 || y < y1){ y1 = y; } if(y2 == -1 || y > y2){ y2 = y; } } } } return new int[]{x1, y1, (x2-x1), (y2-y1)}; } private int newColor(int color){ int red = (color & 0x00FF0000) >> 16; int green = (color & 0x0000FF00) >> 8; int blue = (color & 0x000000FF); if(red <= green && red <= blue){ red+=5; } else if(green <= red && green <= blue){ green+=5; } else{ blue+=5; } return 0xFF000000 + (red << 16) + (green << 8) + blue; } public static void main(String[] args) { new Logos(); } } 

您可以使用normxcorr2函数简化@ lennon310提出的过程:

 file1='http://i.stack.imgur.com/1KyJA.jpg'; file2='http://i.stack.imgur.com/zyHuj.jpg'; It = imread(file1); Ii = imread(file2); It=rgb2gray(It); Ii=rgb2gray(Ii); It=double(It); % template Ii=double(Ii); % image c=normxcorr2(It, Ii); imagesc(c); 

简单的方法(您不需要编写任何代码) – 使用Adaptive Vision Studio:

  1. AddLoadImage(并选择具有多个徽标的图像)
  2. 添加LocateMultipleObjects_EdgeBased。
  3. 将LoadImage中的outImage连接到第二个filter的inImage
  4. 从LocateMultipleObjects_EdgeBased编辑inEdgeModel,例如我的编辑结果(使用插件中的Load Image加载Model图像): 模型
  5. 运行程序并更改LocateMultipleObjects_EdgeBased的参数以查找所有元素(我将inEdgeMagnitude更改为9.0)。 您还将获得每张图片的分数:带有结果的程序: 在此处输入图像描述

总之,您需要添加两个filter:loadImage和LocateMultipleObjects_EdgeBased并选择要查找的模型:)这对初学者来说是好的,您不需要编写任何高级程序。 您也可以尝试解决它:检测圆圈,TemplateMatching_NCC等…

如果要在更复杂的环境(旋转,变形,缩放,透视)中检测对象,则需要更高效的检测方法。 我建议你看看所谓的“Haarfunction的级联分类器”OpenCv可以为你提供很多function来快速完成这个方法。 看到这个有用的页面

或者甚至通过matlab你可以看到这个例子