Rahul
Rahul

Reputation: 2759

Edge Detection, Image Manipulation, and Final Data Extraction in R

I'm new to this community, and to R, but not new to programming (C, VB, Matlab, APDL etc). I'm creating an engineering evaluation tool for a product, that needs to quantify the quality of the edge of a vane. I'll be evaluating hundreds of such vanes using an automated platform with a webcam in exactly the same place each time - thus will be performing statistical image analysis. I'm not new to statistics, but am completely new to R and digital image processing. (I selected R, since it's free, and I should be able to script in it. If there's a better way to do this, please let me know. Matlab is 2nd choice, because of the cost.)

An original image is shown here: Link

Some basic scripting later:

library(EBImage)
original=readImage("original.jpg")
fhi=matrix(1,nc=3,nr=3)
fhi[2,2]=-8
filtered=filter2(original,fhi)

I selected the EBImage library, based on some initial reading online. Suggest alternatives, if better please.

Filtered image looks like this: Link

What I need to do:

  1. Get the X,Y coordinates of all points on 'Edge 2', that lie between 'Edge 1' and 'Edge 3'. The X,Y origin can be assumed to be the lower left corner of the photo, although, ideally I'd like it to be the intersection of Edge 1 and Edge 2.
  2. Store X,Y coordinates in a matrix with an identifier for the vane number. ("Vane 1", "Vane 2", or just 1,2,... etc)

I'm quite lost on how I proceed from where I am. Appreciate any pointers.

Upvotes: 3

Views: 1472

Answers (2)

Jota
Jota

Reputation: 17611

This is the best I managed to do with finding coordinates of edges. This is a pretty coarse approach, but it should give you some ideas. Let me preface this by saying I know pretty much nothing about image processing. So, one can likely do a lot better with the edge detecting than I did. I used the biOps package.

library(biOps)
original <- readJpeg("original.jpg")

# I did not try hard to detect edges as I don't know what I'm doing.
# If you can do better on the edge detecting, you'll get better results
test <- imgHomogeneityEdgeDetection(imgCanny(original, 2)) 

# did this to work with one of the three (i.e. red, green, blue)
reds <- imgRedBand(test)  # reds only contains values 32 and 255. 255 is "edges"

# find the indices of the "edges"
edgelocations <- which(reds!=32, arr.ind=TRUE)

The origin starts in the upper left corner of the original image. See plot(edgelocations).

So, you can flip it to change the origin:

edgelocations <- which(t(r)[,nrow(r):1]!=32, arr.ind=TRUE)
plot(edgelocations)

enter image description here

Upvotes: 1

Mark Setchell
Mark Setchell

Reputation: 207345

I kind of liked the Canny edge detection in ImageMagick, and got the following from your input photo, using this command:

convert photo.jpg -canny 0x12+10%+30% out.jpg

enter image description here

I then had a try with HoughLinesP from OpenCV, and got the image below:

enter image description here

Using this code which is heavily borrowed from the OpenCV website:

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
   const char* filename = argc >= 2 ? argv[1] : "in.jpg";

   Mat src = imread(filename, 0);
   if(src.empty())
   {
      cout << "can not open " << filename << endl;
      return -1;
   }

   Mat dst, cdst;
   dst=src;
   cvtColor(src, cdst, CV_GRAY2BGR);

   vector<Vec4i> lines;
   HoughLinesP(dst, lines, 1, CV_PI/90, 150, 300, 50 );

   printf("Lines detected: %d\n",(int)lines.size());
   for( size_t i = 0; i < lines.size(); i++ )
   {
      Vec4i l = lines[i];
      line( cdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, CV_AA);
   }

   imshow("source", src);
   imshow("detected lines", cdst);

   waitKey();
   return 0;
}

ADDITIONAL MATERIAL

Thanks to @dlemstra for the input about ImageMagick supporting HoughLines too, with that advice, I did the following in s single invocation of ImageMagick (without using OpenCV):

convert photo.jpg \
\( +clone -canny 0x5+10%+30% -write photo_canny.jpg \
-background none -fill red -stroke red -strokewidth 2 \
-hough-lines 9x9+150 -write photo_lines.jpg \) -composite photo_hough.jpg

And it looks like this:

enter image description here

I wonder about rotating the image after finding the long upright edge so that it is vertical and then cutting the image along that line and looking for the horizontal edge at bottom left either using different parameters or after stretching the width of the image to emphasize the horizontal line...

Upvotes: 1

Related Questions