【问题标题】:Simple Image Recognition in processing.orgprocessing.org 中的简单图像识别
【发布时间】:2017-07-11 04:55:06
【问题描述】:

我正在尝试编写最简单的图像比较函数。 这个想法是有一个目标图像和n个不同图像的集合。

目标是选择与目标图像最相似的图像。

到目前为止,我的方法包括在调整大小的图像中定义从像素到像素的欧几里德 HSB 距离,并且一直在尝试执行返回获胜者图像的 PImage 函数。我已经编写了一个float 函数,该函数将图像列表从赢家排到输家,但我想跳过这一步以使过程更加简洁。

问题出在PImage difference(PImage){ 函数,程序输出错误就行了:

        float x1 = brightness(imageKey.pixels[i]);

错误是 ArrayIndexOutOfBoundsException

这是完整的代码:

//CLICK ON S TO SAVE FRAMES TO FOLDER


int series = 50; //
PImage[] collection = new PImage[series];

PImage imageKey,imageKey2, imageKeyHUE, imageKeySUM, imageKeySAT; //target image alias with ready operations
int imageWidth = 800;
int leftAlign = 850  ;

void setup()
{
size(1200,600);
background(255);
frameRate(random(1,10.0));

for ( int i = 0; i< collection.length; i++ )
{
collection[i] = loadImage( "Image_"+ i + ".jpg" );  
}

//_____________________________________________TARGET IMAGE AND NAME TEXT

textSize(10);
fill(0);
text("target image", leftAlign, 220);
textSize(15);
text("central london", leftAlign, 240);
text("comparison methods", leftAlign, 290);
//_____________________________________________________________________BUTTONS
imageKey = loadImage("Image_0.jpg");
imageKey.resize(240, 180);
image(imageKey, leftAlign,25);

   imageKeySAT= loadImage("Image_0.jpg");
    imageKeySAT.resize(60,60);
    imageKeySAT = saturation(imageKeySAT);
    image(imageKeySAT, leftAlign+140,300);

      imageKeySUM = loadImage("Image_0.jpg");
      imageKeySUM.resize(60,60);
      imageKeySUM = sum(imageKeySUM);
      image(imageKeySUM, leftAlign+70,300);

          imageKeyHUE = loadImage("Image_0.jpg");
          imageKeyHUE.resize(60,60);
          imageKeyHUE = hue(imageKeyHUE);
          image(imageKeyHUE, leftAlign,300);

          textSize(20);
          text("CLICK HERE TO", leftAlign, 430);
          text("STOP AT WINNER", leftAlign, 450);



}


void draw()
{

//______________________________________________SHOW IMAGES ARRAY
image(collection[int(random(0,series))],0,0);

//______________________________________________HISTOGRAMS
histogramhue();
histogramsat();
histogrambright();

//______________________________________________SUM METHOD
//float Vector_Approach(PImage sumSatin){


//}

}


void keyPressed()
{
  if(key=='s') saveFrame("images/image-######.jpg");
}


PImage difference(PImage satin)
{
  colorMode(HSB);

    satin.loadPixels();
    imageKey.loadPixels();

    PImage satout = createImage(satin.width, satin.height, RGB);

    satout.loadPixels();
    for(int i = imageWidth; i<satout.pixels.length-imageWidth; i++)
    {
        float x1 = brightness(imageKey.pixels[i]);
        float b0 = brightness(satin.pixels[i]);
       // float y1 = brightness(satin.pixels[i+1]);

        float value = x1-b0;

        satout.pixels[i] = color(0,0,value);

    }
    satout.updatePixels();

    return satout;    
}

void mouseReleased(){
//______________________________________________BUTTON OVER
for ( int i = 0; i< collection.length; i++ )
  if (mouseX > leftAlign && mouseX < (leftAlign + 60) && mouseY > 300 && mouseY < 360){

            collection[i] = loadImage( "Image_"+ i + ".jpg" );  
            collection[i] = hue(collection[i]); histogramhue();
                  noStroke(); fill(255); rect(leftAlign,360,200,40); fill(0);
                  textSize(10);text("comparison by hue", leftAlign, 380);

} else if (mouseX > (leftAlign + 70) && mouseX < (leftAlign + 130) && mouseY > 300 && mouseY < 360)
{

            collection[i] = loadImage( "Image_"+ i + ".jpg" );  
            collection[i] = sum(collection[i]);
                  noStroke(); fill(255); rect(leftAlign,360,200,40); fill(0);
                  textSize(10);text("comparison by sum", leftAlign, 380);

}else if (mouseX > (leftAlign + 140) && mouseX < (leftAlign + 200) && mouseY > 300 && mouseY < 360)
{

          collection[i] = loadImage( "Image_"+ i + ".jpg" );  
          collection[i] = saturation(collection[i]);
                  noStroke(); fill(255); rect(leftAlign,360,200,40); fill(0);
                  textSize(10);text("comparison by saturation", leftAlign, 380);


}else if (mouseX > leftAlign && mouseX < 1200 && mouseY > 340 && mouseY < 600)
{

          collection[i] = loadImage( "Image_"+ i + ".jpg" );  
          collection[i] = difference(collection[i]);
                  noStroke(); fill(255); rect(leftAlign,360,200,40); fill(0);
                  textSize(10);text("WINNER IMAGE!!!!", leftAlign, 380);
}else{

    collection[i] = loadImage( "Image_"+ i + ".jpg" );  
    noStroke(); fill(255); rect(leftAlign,360,200,40); fill(0);

}
}



/*          HSB PImage Methods             */

 //HUE              ------->    /** CHOSEN METHOD**/
 //SATURATION       ------->    /** CHOSEN METHOD**/
 //SUM              ------->    /** CHOSEN METHOD**/





PImage hue(PImage satin)
{
      colorMode(HSB);
      satin.loadPixels();

      PImage satout = createImage(satin.width, satin.height, HSB);

      satout.loadPixels();

      for (int j = 0; j < satout.pixels.length; j++)
      {
      satout.pixels[j] = color(hue(satin.pixels[j]),255,255);
      }

satout.updatePixels();

return satout;
} 

PImage saturation(PImage satin)
{
      colorMode(HSB);
      satin.loadPixels();
      PImage satout = createImage(satin.width, satin.height, RGB);
      satout.loadPixels();
      for (int j = 0; j < satout.pixels.length; j++)
      {
      satout.pixels[j] = color(saturation(satin.pixels[j]));
      }

satout.updatePixels();
//colorMode(RGB);
return satout;
} 



PImage sum(PImage satin)
{
  colorMode(HSB);

    satin.loadPixels();

    PImage satout = createImage(satin.width, satin.height, RGB);

    satout.loadPixels();
    for(int i = imageWidth; i<satout.pixels.length-imageWidth; i++)
    {
        float b0 = brightness(satin.pixels[i]);
        float x1 = brightness(satin.pixels[i-1]);
        float y1 = brightness(satin.pixels[i-imageWidth]);

        float xdiff = b0-x1;
        float ydiff = b0-y1;

        float value = (510 + xdiff + ydiff)/3;

        satout.pixels[i] = color(0,0,value);

    }
    satout.updatePixels();

    return satout;    
}

//REFERENCE HISTOGRAM TAKEN FROM A PROGRAMMING HANDBOOK FOR VISUAL DESIGNERS AND ARTISTS BY BEN FRY ET AL

void histogramhue(){
PImage img = loadImage("Image_0.jpg");
int[] hist = new int[600];

// Calculate the histogram
for (int i = 0; i < img.width; i++) {
  for (int j = 0; j < img.height; j++) {
    int hue = int(hue(get(i, j)));
    hist[hue]++; 
  }
}

int histMax = max(hist);

stroke(255,250); strokeWeight(5);
// Draw half of the histogram (skip every second value)
for (int i = 0; i < img.width; i += 20) {
  int which = int(map(i, 0, img.width, 0, 255));
  int y = int(map(hist[which], 0, histMax, img.height, 0));
  line(i, img.height, i, y);
}}


void histogramsat(){
PImage img = loadImage("Image_0.jpg");

int[] hist = new int[600];

for (int i = 0; i < img.width; i++) {
  for (int j = 0; j < img.height; j++) {
    int sat = int(saturation(get(i, j)));
    hist[sat]++; 
  }
}

int histMax = max(hist);

stroke(255,150);strokeWeight(10);
for (int i = 0; i < img.width; i += 20) {
  int which = int(map(i, 0, img.width, 0, 255));
  int y = int(map(hist[which], 0, histMax, img.height, 0));
  line(i, img.height, i, y);
}}

void histogrambright(){
PImage img = loadImage("Image_0.jpg");

int[] hist = new int[600];


for (int i = 0; i < img.width; i++) {
  for (int j = 0; j < img.height; j++) {
    int bright = int(brightness(get(i, j)));
    hist[bright]++; 
  }
}
int histMax = max(hist);

stroke(255, 150);strokeWeight(20);
for (int i = 0; i < img.width; i += 20) {
  int which = int(map(i, 0, img.width, 0, 255));
  int y = int(map(hist[which], 0, histMax, img.height, 0));
  line(i, img.height, i, y);
}}

【问题讨论】:

  • 由于您想比较图像,您可以使用称为相关的技术。相关范围在 0 - 1 之间。只要被比较的图像彼此接近,则相关因子将接近 1,否则。
  • 只搜索获胜者,即距离最小的图像,无需排序。它不再简洁了。
  • @Trilarion 我很好地理解了这个概念,我只是无法获得 PImage 或 float 函数来输出获胜者图像。有什么帮助吗?
  • @MercedesLanda 根据可用于此任务的时间,您可能还需要考虑比较两个图像之间的平均结构相似性指数。应该可以使用OpenCV PSNR/SSIM example 中的getMSSIM 函数。示例代码是 c++,您不需要 GPU 部分,但您可以使用 OpenCV Processing library 将您的 PImages 转换为 OpenCV 的 Mat 格式,计算 SSIM 然后将结果转换回来

标签: image-processing processing image-recognition


【解决方案1】:

孤立地看,您的功能似乎确实有效:

PImage imageKey,testImage;
int imageWidth = 800;
int imageHeight = 600;

void setup(){
  size(1600,600);
  //fake imageKey
  imageKey = getNoise(imageWidth,imageHeight);

  //fake test image
  testImage = getNoise(imageWidth,imageHeight);

  image(testImage,0,0);
  image(difference(testImage),800,0);
}

PImage getNoise(int width,int height){
  PImage out = createImage(width,height,RGB);

  for(int i = 0 ; i < out.pixels.length; i++) 
    out.pixels[i] = color(random(255),random(255),random(255));

  out.updatePixels();

  return out;
}

PImage difference(PImage satin)
{
  colorMode(HSB);

  satin.loadPixels();
  imageKey.loadPixels();

  PImage satout = createImage(satin.width, satin.height, RGB);

  satout.loadPixels();
  for (int i = imageWidth; i<satout.pixels.length-imageWidth; i++)
  {
    float x1 = brightness(imageKey.pixels[i]);
    float b0 = brightness(satin.pixels[i]);
    // float y1 = brightness(satin.pixels[i+1]);

    float value = x1-b0;
    //println(i,x1,b0,x1-b0,value);

    satout.pixels[i] = color(0, 0, value);
  }
  satout.updatePixels();

  return satout;
}

我无法测试您的实际设置,因为我无法访问您的图像,但 ArrayIndexOutOfBoundsException 可能是因为您的 i 计数器超出了 imageKey 中的像素数。您可以通过检查 i &lt; imageKey.pixels.length 来测试这一点。我的猜测是图像的尺寸不同,因此像素数也不同。

其他稍微偏离主题的注释:

  1. 您的difference() 函数与imageKeyimageWidth 变量紧密耦合。您可能希望使您的函数松散耦合,以便它们可以在其他上下文中轻松重用。您可以先让这两个变量成为函数的额外参数/参数
  2. 您可能还想查看颜色之间的欧式距离(在感知颜色空间中,例如 Lab*)。看看this answer。尽管它是 OpenFrameworks 的答案,但它应该很容易适应 Processing 的 colorPVector 类型。

【讨论】:

    猜你喜欢
    • 2021-11-14
    • 2013-06-07
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 2013-07-11
    • 2011-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多