| LEFT | RIGHT |
|---|---|
| 1 /* | 1 /* |
| 2 Metric | 2 Metric |
| 3 Copyright (C) 2006 Yangli Hector Yee | 3 Copyright (C) 2006 Yangli Hector Yee |
| 4 | 4 |
| 5 This program is free software; you can redistribute it and/or modify it under th e terms of the | 5 This program is free software; you can redistribute it and/or modify it under th e terms of the |
| 6 GNU General Public License as published by the Free Software Foundation; either version 2 of the License, | 6 GNU General Public License as published by the Free Software Foundation; either version 2 of the License, |
| 7 or (at your option) any later version. | 7 or (at your option) any later version. |
| 8 | 8 |
| 9 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; | 9 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
| 10 without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | 10 without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 116 } else { | 116 } else { |
| 117 f[i] = (kappa * r[i] + 16.0f) / 116.0f; | 117 f[i] = (kappa * r[i] + 16.0f) / 116.0f; |
| 118 } | 118 } |
| 119 } | 119 } |
| 120 L = 116.0f * f[1] - 16.0f; | 120 L = 116.0f * f[1] - 16.0f; |
| 121 A = 500.0f * (f[0] - f[1]); | 121 A = 500.0f * (f[0] - f[1]); |
| 122 B = 200.0f * (f[1] - f[2]); | 122 B = 200.0f * (f[1] - f[2]); |
| 123 } | 123 } |
| 124 | 124 |
| 125 | 125 |
| 126 // simple convolution based edge detection. | 126 // simple convolution based edge detection with a 3-by-3 size kernel. |
| 127 void detect_edge(RGBAImage* diff_image, int* edge_image, unsigned int w, unsigne d int h) { | 127 // edgeImg is the result, pixel is either 255 which means an edge point |
|
vangelis
2009/06/30 02:35:05
best to stick with the 80 column limit and break l
| |
| 128 // define the kernel for convolution. | 128 // or 0 means it is not edge, based on whether the result |
| 129 int kernel_length = 3; | 129 // of convolution is larger than pre-defiend threshold or not. |
|
vangelis
2009/06/30 02:35:05
Seems that the current convention for pdiff is to
| |
| 130 int kernel[9] = {-1, -1, -1, -1, 8, -1, -1, -1, -1}; | 130 void DetectEdge(RGBAImage* diffImg, int* edgeImg, unsigned int w, |
| 131 unsigned int x = 0, y = 0; | 131 unsigned int h, int edgeNeighborNum) { |
| 132 int cx = 0, cy = 0; | 132 // define the kernel for convolution. |
| 133 for (y = 0; y < h; y++) | 133 » int kernelLength = 3; |
| 134 for (x = 0; x < w; x++) | 134 » int kernel[9] = {-1, -1, -1, -1, 8, -1, -1, -1, -1}; |
| 135 { | 135 » unsigned int x = 0, y = 0; |
| 136 int index = y * w + x; | 136 » int cx = 0, cy = 0; |
| 137 » » » edge_image[index] = 0; | 137 |
|
vangelis
2009/06/30 02:35:05
watch indentation.
| |
| 138 for (cx = -1; cx <=1; cx++) | 138 // threshold based on edgeNeighborNum |
|
vangelis
2009/06/30 02:35:05
it's good practice to always use curly braces { }
| |
| 139 for (cy = -1; cy <= 1; cy++) | 139 // edgeNeighborNum is the max number of neighbors |
| 140 { | 140 // a pixel could have to be considered as |
| 141 int nx = x + cx; | 141 // edges. |
| 142 int ny = y + cy; | 142 int threshold = (8 - edgeNeighborNum) * 255; |
| 143 if (nx < 0) nx = -nx; | 143 |
|
vangelis
2009/06/30 02:35:05
it seems that instead of wrapping we should clamp
| |
| 144 if (ny < 0) ny = -ny; | 144 » // shrink the image by 1 pixel to avoid checking boundaries. |
| 145 if (nx >= w) nx = 2 * w - nx - 1; | 145 » for (y = 1; y < h - 1; y++) { |
| 146 if (ny >= h) ny= 2 * h - ny - 1; | 146 » » for (x = 1; x < w - 1; x++) { |
| 147 edge_image[index] += diff_image->Get_Red(ny * w + nx) * kern el[(cy + 1) * kernel_length + cx + 1]; | 147 » » » int index = y * w + x; |
|
vangelis
2009/06/30 02:35:05
80 col limit
| |
| 148 } | 148 » » » edgeImg[index] = 0; |
| 149 // make it binary. | 149 » » for (cx = -1; cx <=1; cx++) { |
| 150 if (edge_image[index] > 50) | 150 » » » for (cy = -1; cy <= 1; cy++) { |
|
vangelis
2009/06/30 02:35:05
since 50 is an arbitrary value, it should be expos
| |
| 151 edge_image[index] = 255; | 151 » » » » int nx = x + cx; |
| 152 else | 152 » » » » int ny = y + cy; |
| 153 edge_image[index] = 0; | 153 » » » » edgeImg[index] += |
| 154 } | 154 » » » » diffImg->Get_Red(ny * w + nx) * |
| 155 » » » » kernel[(cy + 1) * kernelLength + cx + 1]; | |
| 156 » » » } | |
| 157 » » } | |
| 158 | |
| 159 » » if (edgeImg[index] >= threshold) | |
| 160 » » » edgeImg[index] = 255; | |
| 161 » » else | |
| 162 » » » edgeImg[index] = 0; | |
| 163 » » } | |
| 164 » } | |
| 155 } | 165 } |
| 156 | 166 |
| 157 bool Yee_Compare(CompareArgs &args) | 167 bool Yee_Compare(CompareArgs &args) |
| 158 { | 168 { |
| 159 if ((args.ImgA->Get_Width() != args.ImgB->Get_Width()) || | 169 if ((args.ImgA->Get_Width() != args.ImgB->Get_Width()) || |
| 160 (args.ImgA->Get_Height() != args.ImgB->Get_Height())) { | 170 (args.ImgA->Get_Height() != args.ImgB->Get_Height())) { |
| 161 args.ErrorStr = "Image dimensions do not match\n"; | 171 args.ErrorStr = "Image dimensions do not match\n"; |
| 162 return false; | 172 return false; |
| 163 } | 173 } |
| 164 | 174 |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 315 if (bZ) delete[] bZ; | 325 if (bZ) delete[] bZ; |
| 316 if (aLum) delete[] aLum; | 326 if (aLum) delete[] aLum; |
| 317 if (bLum) delete[] bLum; | 327 if (bLum) delete[] bLum; |
| 318 if (la) delete la; | 328 if (la) delete la; |
| 319 if (lb) delete lb; | 329 if (lb) delete lb; |
| 320 if (aA) delete aA; | 330 if (aA) delete aA; |
| 321 if (bA) delete bA; | 331 if (bA) delete bA; |
| 322 if (aB) delete aB; | 332 if (aB) delete aB; |
| 323 if (bB) delete bB; | 333 if (bB) delete bB; |
| 324 | 334 |
| 325 » //******************************************************************* | 335 » if (args.IgnoreEdge) |
| 326 » //detect edges here, and protect them to be checked as inconsistece.* | |
|
vangelis
2009/06/30 02:35:05
Not sure I understand the comment here.
| |
| 327 » //******************************************************************* | |
| 328 » if (args.EdgeDetect) | |
| 329 { | 336 { |
| 330 » » int* edge_image = new int[w * h]; | 337 » » int* edgeImg = new int[w * h]; |
| 331 | 338 |
| 332 » » // then run convolution based edge detection algorithm. | 339 » » // run convolution based edge detection algorithm. |
| 333 » » detect_edge(args.ImgDiff, edge_image, w, h); | 340 » » DetectEdge(args.ImgDiff, edgeImg, w, h, args.EdgeNeighborNum); |
| 334 | 341 |
| 335 » » for (y = 0; y < h; y++) { | 342 » » // delete edge pixels from the result image. |
| 336 » » » for (x = 0; x < w; x++) { | 343 » » for (y = 1; y < h - 1; y++) { |
| 344 » » » for (x = 1; x < w - 1; x++) { | |
| 337 unsigned int index = y * w + x; | 345 unsigned int index = y * w + x; |
| 338 if (args.ImgDiff->Get_Red(index) == 255 && | 346 if (args.ImgDiff->Get_Red(index) == 255 && |
| 339 » » » » » » » edge_image[index] == 255 ) | 347 » » » » » edgeImg[index] == 255) { |
|
vangelis
2009/06/30 02:35:05
watch indentation
| |
| 340 » » » » { | |
| 341 args.ImgDiff->Set(0, 0, 0, 255, index); | 348 args.ImgDiff->Set(0, 0, 0, 255, index); |
| 342 pixels_failed--; | 349 pixels_failed--; |
| 343 } | 350 } |
| 344 } | 351 } |
| 345 } | 352 } |
| 346 | 353 |
| 347 » » // output edge image. | 354 » » delete[] edgeImg; |
| 348 » » // generate the file name of the edge image. | 355 » } |
| 349 » » /*std::string ref_name = args.ImgA->Get_Name(); | 356 |
|
vangelis
2009/06/30 02:35:05
If this code is not used, please remove it.
| |
| 350 » » std::string edgeImgName = ref_name.substr(0, ref_name.find(".", 0)); | |
| 351 » » edgeImgName.append("_result_edge"); | |
| 352 » » edgeImgName.append(ref_name.substr(ref_name.find(".", 0), ref_na me.size() - ref_name.find(".", 0))); | |
| 353 » | |
| 354 » » RGBAImage edgeImg(w, h, edgeImgName.c_str()); | |
| 355 » » for (y = 0; y < h; y++) { | |
| 356 » » for (x = 0; x < w; x++) { | |
| 357 » » » int index = y * w + x; | |
| 358 » » » if (edge_image[index] == 255) | |
| 359 » » » » edgeImg.Set(255, 0, 0, 255, index); | |
| 360 » » » else | |
| 361 » » » » edgeImg.Set(0, 0, 0, 255, index); | |
| 362 » » } | |
| 363 » » } | |
| 364 » » edgeImg.WriteToFile(edgeImg.Get_Name().c_str());*/ | |
| 365 | |
| 366 » » delete[] edge_image; | |
| 367 » } | |
| 368 //******************************************************************* | |
|
vangelis
2009/06/30 02:35:05
Do we need this comment here?
| |
| 369 » //detect edges above, and protect them to be checked as inconsistece. | |
| 370 » //******************************************************************* | |
| 371 char different[100]; | 357 char different[100]; |
| 372 sprintf(different, "%d pixels are different\n", pixels_failed); | 358 sprintf(different, "%d pixels are different\n", pixels_failed); |
| 373 | 359 |
| 374 // Always output image difference if requested. | 360 // Always output image difference if requested. |
| 375 if (args.ImgDiff) | 361 if (args.ImgDiff) |
| 362 { | |
|
vangelis
2009/07/09 02:43:29
seems to be some extra whitespace after the { . Pl
| |
| 376 if (args.ImgDiff->Get_Name().size() > 0) { | 363 if (args.ImgDiff->Get_Name().size() > 0) { |
| 377 » » » if (args.ImgDiff->WriteToFile(args.ImgDiff->Get_Name().c _str())) { | 364 » » » if (args.ImgDiff->WriteToFile( |
| 365 args.ImgDiff->Get_Name().c_str())) { | |
| 378 args.ErrorStr += "Wrote difference image to "; | 366 args.ErrorStr += "Wrote difference image to "; |
| 379 args.ErrorStr+= args.ImgDiff->Get_Name(); | 367 args.ErrorStr+= args.ImgDiff->Get_Name(); |
|
vangelis
2009/06/30 02:35:05
Looks like there's tabs in there. Please remove..
| |
| 380 args.ErrorStr += "\n"; | 368 args.ErrorStr += "\n"; |
| 381 } else { | 369 } else { |
| 382 » » » » args.ErrorStr += "Could not write difference ima ge to "; | 370 » » » » args.ErrorStr += |
| 371 "Could not write difference image to "; | |
| 383 args.ErrorStr+= args.ImgDiff->Get_Name(); | 372 args.ErrorStr+= args.ImgDiff->Get_Name(); |
| 384 args.ErrorStr += "\n"; | 373 args.ErrorStr += "\n"; |
| 385 } | 374 } |
| 386 } | 375 } |
| 387 | 376 » } |
| 388 if (pixels_failed < args.ThresholdPixels) { | 377 if (pixels_failed < args.ThresholdPixels) { |
| 389 args.ErrorStr = "Images are perceptually indistinguishable\n"; | 378 args.ErrorStr = "Images are perceptually indistinguishable\n"; |
| 390 args.ErrorStr += different; | 379 args.ErrorStr += different; |
| 391 return true; | 380 return true; |
| 392 } | 381 } |
| 393 | 382 |
| 394 args.ErrorStr = "Images are visibly different\n"; | 383 args.ErrorStr = "Images are visibly different\n"; |
| 395 args.ErrorStr += different; | 384 args.ErrorStr += different; |
| 396 | 385 |
| 397 return false; | 386 return false; |
| 398 } | 387 } |
| LEFT | RIGHT |