├── README.md ├── autofocus.py └── find_best_focus_point.m /README.md: -------------------------------------------------------------------------------- 1 | # Edge Detection Based Autofocus Algorithm to Detect Accurate Camera Working Distance 2 | ## Working Principle 3 | 4 | This is the Python and Matlab implementation of our article named "Edge Detection Based Autofocus Algorithm to Detect Accurate Camera Working Distance" accepted by ISITES2022. Please feel free to use and give feedback. 5 | 6 | ![ezgif com-gif-maker (2)](https://user-images.githubusercontent.com/52501795/192199941-a4685fe7-1dde-453f-888c-bd3a8c817498.gif) 7 | 8 | ## Algorithm 9 | As can be seen in Figure, a part of a circular geometry part image where we can see the edge information is framed in red. The frame marked here is shown zoomed in Figure (c)(d)(e). If the distance between the part and the camera is closer than the optimum focal distance, the blurred image seen in Figure (c) will be obtained. As you can see, the transition is smoother and longer. If the distance between the part and the camera is further than the optimum focal distance, a similar blurred image is obtained, as can be seen in Figure (e). However, as in Figure (d), the clearest image is obtained when the distance between the camera and the part is optimally 10 | adjusted. The transition in the edge regions is narrower, the amount of change between the intensity values is higher. From this point of view, edge information contains critical clues about focusing. 11 | 12 | ![image](https://user-images.githubusercontent.com/52501795/192207154-857ad214-06e2-42dc-9244-3be2b156b6c7.png) 13 | 14 | First, images of the object are taken with an industrial camera at ε distance intervals. For each captured image, small objects in the image are eliminated and the gradient of the image is found. In order to find the median value of the image significant, all elements with zero value in the obtained image are assigned as undefined. Then all elements in the array that are smaller than the product of the found median value and ς are assigned zero. Finally, a new value is obtained by summing all the elements in the resulting array. The higher this value, the sharper the image. 15 | ![ezgif com-gif-maker (3)](https://user-images.githubusercontent.com/52501795/192206291-f01f44dc-dea3-4d06-b13c-bad642a454f7.gif) 16 | 17 | ## Requirements 18 | ###### Execution Environment 19 | - Python 3 or Matlab 20 | ###### Packages 21 | - Numpy 1.22.4 22 | - Matplotlib 3.5.2 23 | - OpenCV 4.6.0.66 24 | - SciPy 1.8.1 25 | 26 | ## Usage 27 | You can use the naming in line 16 of the code by adapting it for your own pictures. The x value in line 10 will be your ς value. Also this code is written in a for loop. If you want, you can apply it one by one by taking it out of the for loop according to the application area. 28 | 29 | ## Reference 30 | Please cite this article: "Edge Detection Based Autofocus Algorithm to Detect Accurate Camera Working Distance" Poyraz A.G., Kacmaz M., ISITES'2022 31 | https://doi.org/10.33793/acperpro.05.03.7422 32 | -------------------------------------------------------------------------------- /autofocus.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | import cv2 4 | import matplotlib.pyplot as plt 5 | import numpy as np 6 | from scipy.interpolate import BSpline, make_interp_spline 7 | 8 | class AutoFocus: 9 | def __init__(self) -> None: 10 | self.k = 700 11 | self.height_list = [] 12 | self.height_listmag_list = [] 13 | self.x = 10 14 | 15 | def autofocus(self): 16 | """ 17 | Generate the function comment for the given function body in a markdown code block with the correct language syntax. 18 | This code defines a function called autofocus that performs some image processing operations. It takes no arguments and returns 19 | two arrays, xnew and power_smooth. 20 | 21 | The function iterates over a range of values, appends values to a list, and performs image processing operations on each iteration. 22 | It uses the OpenCV library to apply Sobel operators to calculate the gradient magnitude of the image. It then calculates the median 23 | of the gradient magnitudes and filters out values below a certain threshold. The function also calculates the sum of the filtered 24 | gradient magnitudes and appends it to another list. 25 | 26 | Finally, the function converts the lists to numpy arrays, creates a new array xnew using the minimum and maximum values from 27 | height_list, and applies a spline interpolation to smooth the height_listmag_list values. The smoothed values are stored in power_smooth 28 | and both xnew and power_smooth are returned from the function. 29 | Returns: 30 | xnew (numpy.ndarray): An array of x-axis values. 31 | power_smooth (numpy.ndarray): An array of smoothed y-axis values. 32 | """ 33 | for i in range(21): 34 | self.height_list.append(k) 35 | k +=10 36 | 37 | self.k = 700 38 | for i in range(21): 39 | img = cv2.imread(str(self.k) + ".bmp",0) 40 | 41 | #print("cropped/" + str(k) + ".bmp___________________") 42 | sobelx = cv2.Sobel(img,cv2.CV_64F,1,0) 43 | sobely = cv2.Sobel(img,cv2.CV_64F,0,1) 44 | 45 | 46 | Gmag = np.sqrt(sobelx*sobelx + sobely*sobely) 47 | Gmag = Gmag.flatten() 48 | #Gdir = np.arctan2(sobely, sobelx) * (180 / np.pi) 49 | 50 | #Gmag = np.where(Gmag == 0, np.nan, Gmag) 51 | Gmag = Gmag[Gmag!=0] 52 | 53 | ortanca_deger = np.median(Gmag) 54 | print(ortanca_deger) 55 | #print(str(k) + " - MEDIAN = ", ortanca_deger) 56 | 57 | ortanca_deger3 = ortanca_deger*self.x 58 | #Gmag = np.where(Gmag < (ortanca_deger3), np.nan, Gmag) 59 | Gmag = Gmag[Gmag>ortanca_deger3] 60 | 61 | print(str(self.k) + " - SUM = ", np.sum(Gmag)) 62 | self.height_listmag_list.append(np.sum(Gmag)) 63 | self.k +=10 64 | 65 | self.height_list = np.array(self.height_list); self.height_listmag_list = np.array(self.height_listmag_list) 66 | 67 | xnew = np.linspace(self.height_list.min(), self.height_list.max(), 30000) 68 | spl = make_interp_spline(self.height_list, self.height_listmag_list, k=3) # type: BSpline 69 | power_smooth = spl(xnew) 70 | 71 | return xnew, power_smooth 72 | 73 | def plot(self, xnew, power_smooth): 74 | """ 75 | Plots the given data using matplotlib. 76 | This code defines a method called plot that uses matplotlib to plot data. It takes in two parameters, xnew and power_smooth, 77 | which are arrays of x-values and y-values respectively. The method plots the data using plt.plot, adds a legend, sets labels 78 | for the x-axis and y-axis, scales the y-axis using a symlog scale, and sets a title for the plot. Finally, it displays the plot 79 | using plt.show. 80 | Parameters: 81 | xnew (array-like): The x-values of the data. 82 | power_smooth (array-like): The y-values of the data. 83 | Returns: 84 | None 85 | """ 86 | plt.plot(xnew, power_smooth, label="P Values for Every ε Position") 87 | #plt.plot(self.height_list, self.height_listmag_list, label="P Values for Every ε Position") 88 | plt.legend() 89 | plt.xlabel("ε Values") 90 | plt.ylabel("P Values") 91 | plt.yscale('symlog') 92 | plt.title("ς = {}".format(self.x)) 93 | plt.show() 94 | -------------------------------------------------------------------------------- /find_best_focus_point.m: -------------------------------------------------------------------------------- 1 | %% Find best focus point by changing heigth value based on image gradient 2 | function [best_point] = find_best_focus_point(threshold_for_elimination) 3 | resimler = dir('*.bmp'); 4 | 5 | for i=15%1:numel(resimler) 6 | im = imread(fullfile(resimler(i).name)); 7 | [im_desired] = eliminate_small_objects(im,250); 8 | [Gmag,Gdir] = imgradient(im_desired,'sobel'); 9 | Gmag(Gmag==0) = []; % resimdeki 0 olan bölgeleri temizliyoruz ki sadece değişim olan yerler kalsın 10 | ortanca_deger = median(Gmag); 11 | ortanca_deger3 = ortanca_deger*3; %3 mediandan büyükler anlamlidir 12 | Gmag(Gmag