Detecting multiple images in a single image
我需要帮助识别边界,并将图像与原始图像进行比较。我需要指导如何通过处理或matlab或任何初学者可以实现这一点。例如,看看下面的图片。
原始图像:
多重图像:
您显示的"多个图像"很容易处理,只需简单的图像处理,不需要模板匹配:)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | % 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 |
您可以使用相关方法定位多个图像:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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)) |
结果将为您提供具有最大值的位置:
获取Maxima坐标,将模板质心定位在同一位置,检查模板与匹配图像之间的差异。
我不确定你所说的"识别边界"是什么意思,但是你可以用Canny探测器提取边缘:
1 2 3 | bw=edge(It); bw=imfill(bw,'holes'); figure,imshow(bw) |
下面给出了一个用Java实现的马尔文图像处理框架的解决方案。
途径:
比较方法(在diff插件中):
对于两个徽标中的每个像素,比较每个颜色组件。如果一种颜色组件的差异高于给定阈值,则考虑两个徽标的像素不同。计算不同像素的总数。如果两个徽标的像素数不同于另一个阈值,则认为它们不同。重要提示:此方法对旋转和透视变化非常敏感。
由于您的样本("多个图像")只有古柯商标,我冒昧地加入了另一个商标,以断言算法。
多重图像2
产量
在另一个测试中,我又加了两个类似的古柯商标。更改阈值参数,您可以指定是想要完全相同的徽标还是接受其变化。在下面的结果中,参数被设置为接受徽标变化。
多重图像3
产量
源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | 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<Integer> 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<subimages.length; i++){ diff.setAttribute("comparisonImage", subimages[i]); diff.setAttribute("colorRange", 30); diff.process(target, null, attrOut); if((Integer)attrOut.get("total") < (50*50)*0.6){ original.drawRect(rects[i][0], rects[i][6], rects[i][7], rects[i][8], 6, Color.green); } } } private MarvinImage segmentTarget(){ MarvinImage original = MarvinImageIO.loadImage("./res/logos/target.jpg"); MarvinImage target = original.clone(); threshold.process(target, target); MarvinImage image2 = new MarvinImage(target.getWidth(), target.getHeight()); fill(target, image2); LinkedHashSet<Integer> objects = filterByMass(image2, 10000); int[][] rects = getRects(objects, image2, target); MarvinImage[] subimages = getSubimages(rects, original); return subimages[0]; } private int[][] getRects(LinkedHashSet<Integer> objects, MarvinImage mask, MarvinImage original){ List<int[]> ret = new ArrayList<int[]>(); for(Integer color:objects){ ret.add(getObjectRect(mask, color)); } return ret.toArray(new int[0][0]); } private MarvinImage[] getSubimages(int[][] rects, MarvinImage original){ List<MarvinImage> ret = new ArrayList<MarvinImage>(); 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<imageIn.getHeight(); y++){ for(int x=0; x<imageIn.getWidth(); x++){ if(imageOut.getIntColor(x,y) == 0 && imageIn.getIntColor(x, y) != 0xFFFFFFFF){ fill.setAttribute("x", x); fill.setAttribute("y", y); fill.setAttribute("color", color); fill.setAttribute("threshold", 120); fill.process(imageIn, imageOut); color = newColor(color); found = true; break Outerloop; } } } if(!found){ break; } } } private LinkedHashSet<Integer> filterByMass(MarvinImage image, int mass){ boolean found; HashSet<Integer> analysed = new HashSet<Integer>(); LinkedHashSet<Integer> ret = new LinkedHashSet<Integer>(); while(true){ found=false; outerLoop: for(int y=0; y<image.getHeight(); y++){ for(int x=0; x<image.getWidth(); x++){ int color = image.getIntColor(x,y); if(color != 0){ if(!analysed.contains(color)){ if(getMass(image, color) >= 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<image.getHeight(); y++){ for(int x=0; x<image.getWidth(); x++){ if(image.getIntColor(x, y) == color){ total++; } } } return total; } private int[] getObjectRect(MarvinImage mask, int color){ int x1=-1; int x2=-1; int y1=-1; int y2=-1; for(int y=0; y<mask.getHeight(); y++){ for(int x=0; x<mask.getWidth(); x++){ if(mask.getIntColor(x, y) == color){ if(x1 == -1 || x < x1){ x1 = x; } if(x2 == -1 || x > 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(); } } |
您可以使用
1 2 3 4 5 6 7 8 9 10 11 | 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); |
简单的方法(您不需要编写任何代码)-使用自适应视觉工作室:
总之,您需要添加两个过滤器:LoadImage和locatemultipleObjects,然后选择要查找的模型:)这对初学者很好,您不需要编写任何高级程序。你也可以尝试解决它:检测圆,模板等。
如果要在更复杂的环境(旋转、变形、缩放、透视)中检测对象,则需要更高效的检测方法。我建议您看看所谓的"haar特性的级联分类器"。opencv可以为您提供很多快速完成这个方法的功能。看到这个有用的页面
甚至通过matlab,你也可以看到这个例子。