我需要帮助来识别边框并将图像与原始图像进行比较。我需要指导如何通过处理或matlab或任何初学者来实现这一目标。例如,请看下面的图片。
原始图片:
多张图片:
答案 0 :(得分:24)
您展示的“多个图像”很容易使用简单的图像处理来处理,不需要模板匹配:)
% 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 :(得分:22)
您可以使用相关方法来定位多个图像:
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))
结果将为您提供具有最大值的位置:
获取最大坐标,并将模板质心放在同一位置,检查模板与匹配图像之间的差异。
我不确定“识别边框”是什么意思,但你总是可以用精确探测器提取边缘:
bw=edge(It);
bw=imfill(bw,'holes');
figure,imshow(bw)
答案 2 :(得分:11)
下面介绍了使用Marvin图像处理框架在Java中实现的解决方案。
<强>方法强>
比较方法(内部差异插件):
对于两个徽标中的每个像素,比较每个颜色分量。如果一个颜色分量的差异高于给定阈值,则考虑该两个徽标的像素不同。计算不同像素的总数。如果两个徽标的许多不同像素高于另一个阈值,请将它们视为不同。 重要事项:此方法对旋转和透视变化非常敏感。
由于你的样本(“多图像”)只有古柯标识,我冒昧地包含另一个标识以断言算法。
多张图片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<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();
}
}
答案 3 :(得分:9)
您可以使用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);
答案 4 :(得分:3)
简单的方法(您不需要编写任何代码) - 使用Adaptive Vision Studio:
总之,您需要添加两个过滤器:loadImage和LocateMultipleObjects_EdgeBased并选择要查找的模型:)这对初学者来说是好的,您不需要编写任何高级程序。您也可以通过以下方式尝试解决:检测圈子,TemplateMatching_NCC等...
答案 5 :(得分:1)
如果要在更复杂的环境(旋转,变形,缩放,透视)中检测对象,则需要更高效的检测方法。我建议你看看所谓的“Haar功能的级联分类器” OpenCv可以为您提供很多功能来快速完成此方法。见useful page
或者甚至通过matlab,你可以看到这个example