1

Goal

My goal is to detect PV modules on the dataset of infrared images. After the preprocessing phase, which is mainly removing noisy background, I want to find edges so they can be used for further processing (HoughLinesP etc.). I get already quite satisfying results, however, I’d like to verify my approach and ask for tips.

Attention images (preprocessed, background removed)

preprocessed_1

preprocessed_2

preprocessed_3

Then I increase contrast (that gives me slightly better results)

And then apply Canny Edge detection with some erosion and dilatation.

Final results

canny_1

canny_2

canny_3

I would like to improve detection for images looking similar to the 3rd image - the edges are not detected on the left and right on both rectangles (middle is fine). I tried to increase the contrast and it worked fine on that particular image but it also resulted in more false edges to be detected on other images from my dataset. Is there a way to tackle it better?

Code

In case my approach makes sense there is my code.

import cv2
import numpy as np


def increase_contrast(input_image):
   bgr_image = cv2.cvtColor(input_image, cv2.COLOR_GRAY2BGR)
   lab = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2LAB)

   l, a, b = cv2.split(lab)
   clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
   cl = clahe.apply(l)

   limg = cv2.merge((cl, a, b))

   increased_contrast_image = cv2.cvtColor(limg, cv2.COLOR_LAB2BGR)
   return increased_contrast_image


def detect_edges(input_image):
   hysteresis_min_thresh = 35
   hysteresis_max_thresh = 45

   canny_image = cv2.Canny(image=input_image, threshold1=hysteresis_min_thresh, threshold2=hysteresis_max_thresh,
                           apertureSize=3)

   kernel_size = (7, 7)
   kernel_shape = cv2.MORPH_CROSS
   kernel = cv2.getStructuringElement(kernel_shape, kernel_size)

   dilation_steps = 4
   dilated = cv2.dilate(canny_image, (3, 3), iterations=dilation_steps)

   size = np.size(dilated)
   skel = np.zeros(dilated.shape, np.uint8)

   img = dilated
   done = False

   while not done:
       eroded = cv2.erode(img, kernel)
       temp = cv2.dilate(eroded, kernel)
       temp = cv2.subtract(img, temp)
       skel = cv2.bitwise_or(skel, temp)
       img = eroded.copy()

       zeros = size - cv2.countNonZero(img)
       if zeros == size:
           done = True

   return skel


def process_image(img_path):
   input_image = cv2.imread(img_path)
   input_image = cv2.cvtColor(input_image, cv2.COLOR_BGR2GRAY)
   increased_contrast_image = increase_contrast(input_image)

   cv2.imshow('increased_contrast_image', increased_contrast_image)

   image_scaling = 3
   scaled_image = cv2.resize(src=increased_contrast_image, dsize=(0, 0), fx=image_scaling, fy=image_scaling)
   gaussian_blur = 7
   blurred_image = cv2.blur(scaled_image, (gaussian_blur, gaussian_blur))

   canny_image = detect_edges(blurred_image)
   cv2.imshow('canny_image', canny_image)
   cv2.waitKey()


# DON'T FORGET TO VERIFY THIS PATH
img_path = "data/plasma_results/background/9.JPG"
process_image(img_path)

Questions

Is my approach (Canny) valid and sensical approach for this case?

How can I improve my algorithm so it works better on images with less visible edges between modules?

Edit

Original images

As requested in the comments these are unprocessed infrared images in plasma palette.

plasma_1

plasma_2

plasma_3

AndrewM
  • 69
  • 5
  • everyone loves canny but its so finicky bc it needs the right parameters to work so i dont like to use it for an automated solution bc its not robust to all situations. i recommend trying any other edge detection or morphologyEx tophat/blackhat/gradient. I also recommend using GaussianBlur instead of normal blur, and incase you want to preserve the lines for line detection, you can use bilateralFilter which blurs yet keeps the lines sharp (but alot slower) – Ta946 Jun 14 '21 at 06:37
  • Please provide some original, unprocessed images. – HansHirse Jun 14 '21 at 07:29
  • @Ta946: "i recommend trying any other edge detection": usually, alternative method perform *worse*. –  Jun 14 '21 at 07:38
  • 1
    Possibly an XY question. You say that you need the edges "for further processing". Would be interesting to know what exactly you want to do. Because it seems that the geometry is pretty well repeating and you could find the edges indirectly, or predict all edges from only a few of them. Contrary to the belief of many beginners, edge detection if often a bad idea. (Not counting that this is a case of *ridge* detection.) By the way, maybe the answer lies in the removed background :-) –  Jun 14 '21 at 07:42
  • @Ta946, thanks - I'll try Gaussian and bilateralFilter. – AndrewM Jun 14 '21 at 08:50
  • @HansHirse, unprocessed images added. I intentionally added infrared plasma images instead of grayscale. Please let me know if it would be better to convert in into grayscale whether my code for removing background can help. – AndrewM Jun 14 '21 at 08:54
  • @Ta946, basically I use HoughLinesP to detect segments, then cluster them and make clusters' clean up. Then I detect intersection and rectangles :) I follow this project https://github.com/cdeldon/thermography/blob/master/thermography/detection/segment_detection.py It works pretty well. However, IMO, preprocessing and edges detection should be improved because gaps between modules on images from my dataset are sometimes not very well visible. – AndrewM Jun 14 '21 at 08:58
  • You are applying edge detection to a problem that requires line detection. This is why you see two parallel detections for each line in your image. https://stackoverflow.com/a/50359884/7328782 – Cris Luengo Jun 14 '21 at 15:45
  • @CrisLuengo, sorry for not being clear enough. The problem is not with two parallel detections for each line. I am using HoughLinesP in further processing to detect lines from detected edges and it works pretty well with some minor exceptions. My question is rather about improving preprocessing phase so the whole algorithm works better on all of my images - even these images that have edges not visible very well (f.e. 3rd image) without a need to provide different parameters for different images (it should automated solution). Thanks! – AndrewM Jun 14 '21 at 18:45
  • Does this answer your question? [Edge detection on photovoltaic modules on infrared images](https://stackoverflow.com/questions/67939453/edge-detection-on-photovoltaic-modules-on-infrared-images) –  Jun 15 '21 at 13:30
  • @YvesDaoust, actually this is my initial question in which I was advised not to ask for improving my algorithm and ask for the approach validation instead. Currently I'm trying to use adaptative threshold to make the edges more visible which works really fine for scratching the gaps between the panels. However, it also has its drawbacks as it creates the edges in place of sun reflections (f.e. 1st image) – AndrewM Jun 15 '21 at 15:02

0 Answers0