This is a desktop application for image processing using the OpenCV package. The most important advantage of the application is the ease of use, the ability to immediately visualize the changes made to the image. The user also has the option of adjusting the parameters of each image processing method. In addition, the user can simultaneously visualize the histogram of the processed image in RGB and gray scale. The project can be used to familiarize yourself with image processing methods using the OpenCV package and to process various types of images according to your preferences.
- Colorspace
- Low-pass filters
- High-pass filters
- Thresholding
- Morphological Transformation
- Geometric Transformation
- Brightness
- Histogram
The GUI is developed based on the Qt environment. It was developed using Python3 and PyQt5 version 5. The libraries used in the project are the OpenCV package, the numpy library and matplotlib.
The GUI allows to visualize and convert the image in BGR (default for OpenCV), RGB, HSV and grayscale. The image is automatically opened in RGB when it is loaded using the imread() function. To convert the color scale, we use the built-in cvtColor() function of the opencv library. The user can change the values of individual channels using sliders displayed in an additional window. BGR RGB HSV GRAY
Low pass filtering is used to remove noises from a digital image by image blurring. It is achieved by convolving the image with a low-pass filter kernel. It actually removes high frequency content (eg: noise, edges) from the image. So edges are blurred a little bit in this operation. When using each of the filters, the user can adjust the size of the kernel using the sliders in the additional window. All low-pass filtering was done in the image below. 2D Convolution 2D Convolution filtering use a 2D convolution of the kernel with the image. This is done by the OpenCV function cv.filter2D(). The function applies an arbitrary linear filter to an image. In-place operation is supported. When the aperture is partially outside the image, the function interpolates outlier pixel values according to the specified border mode. The function does actually compute correlation, not the convolution: The effect of applying the 2D convolutional filter on image is presented below. Image Blurring The most used averaging blurring is done by convolving image with a normalized box filter. It simply takes the average of all the pixels under kernel area and replace the central element. This is done by the OpenCV function cv.blur(). The function smooths an image using the kernel: The effect of applying the averaging filter on image is presented below. Gaussian Blurring In this, instead of box filter, gaussian kernel is used. This is done by the OpenCV function cv.GaussianBlur(). Gaussian kernel standard deviations are zeros and they are computed from ksize.width and ksize.height. The form of the Gaussian filter coefficient matrix: The effect of applying the gaussian filter on image is presented below. Median Blurring The function takes median of all the pixels under kernel area and central element is replaced with this median value. This is highly effective against salt-and-pepper noise in the images. Median blurring is done by the OpenCV function cv.medianBlur(). The function smoothes an image using the median filter with the ksize × ksize aperture. The effect of applying the median filter on image is presented below. Bilateral filtering Bilateral filter takes a gaussian filter in space and gaussian filter as a function of pixel difference. Gaussian function of space make sure only nearby pixels are considered for blurring while gaussian function of intensity difference make sure only those pixels with similar intensity to central pixel is considered for blurring. It is highly effective in noise removal while keeping edges sharp. But the operation is slower compared to other filters. Bilateral filtering is done by the OpenCV function cv.bilateralFilter(). The effect of applying the median filter on image is presented below.
A high pass filter is the basis for most sharpening methods. An image is sharpened when contrast is enhanced between adjoining areas with little variation in brightness or darkness. A high pass filter tends to retain the high frequency information within an image while reducing the low frequency information. When using each of the filters, the user can adjust the size of the kernel and along which edge the filtering will be performed in the additional window. Sobel filtering Sobel operators is a joint Gaussian smoothing plus differentiation operation, so it is more resistant to noise. You can specify the direction of derivatives to be taken, vertical or horizontal. Sobel filtering is done by the OpenCV function cv.Sobel(). Filtering with horizontal derivatives Filtering with vertical derivatives Scharr filtering This is a filtering method used to identify and highlight gradient edges/features using the first derivative. Performance is quite similar to the Sobel filter. The Scharr filter can be obtained when the kernel size of the Sobel filter is equal to -1. The filter is automatically set to a 3x3 size, which gives better results than the Sobel 3x3 filter. Filtering with horizontal derivatives Filtering with vertical derivatives Laplacian filtering This is a filtering method used to identify and highlight fine edges based on the second derivative. Laplacian uses one symmetrical kernel while Sobel and Scharr use horizontal and vertical kernels. It is also more sensitive to noise compared to the previous ones. When using each of the filters, the user can adjust the size of the kernel using the sliders in the additional window. Laplacian filtering is done by the OpenCV function cv.Laplacian(). The effect of applying the laplacian filter on image is presented below. Canny edge detection Noise Reduction Canny Edge Detection is a popular edge detection algorithm. Since edge detection is susceptible to noise in the image, first step is to remove the noise in the image with a 5x5 Gaussian filter. Next step is filtering image with a Sobel kernel in both horizontal and vertical direction to get first derivative in both directions. From these two images, we can find edge gradient and direction for each pixel. Gradient direction is always perpendicular to edges. It is rounded to one of four angles representing vertical, horizontal and two diagonal directions. Next a full scan of image is done to remove any unwanted pixels which may not constitute the edge. For this, at every pixel, pixel is checked if it is a local maximum in its neighborhood in the direction of gradient. Last step is decides which are all edges are really edges and which are not. For this, we need two threshold values, minVal and maxVal. Any edges with intensity gradient more than maxVal are sure to be edges and those below minVal are sure to be non-edges, so discarded. Those who lie between these two thresholds are classified edges or non-edges based on their connectivity. If they are connected to "sure-edge" pixels, they are considered to be part of edges. Otherwise, they are also discarded. Canny edge detection algorithm is done by the OpenCV function cv.Canny(). When using each of the filters, the user can adjust levels of first and second thresholds for the hysteresis procedures by using the sliders in the additional window. The effect of applying the canny edge detection algorithm on image is presented below.
Image thresholding is a simple form of image segmentation. It is a way to create a binary image from a grayscale or full-color image. This is typically done in order to separate object or foreground pixels from background pixels to aid in image processing. Thresholding is done by the OpenCV function cv.threshold(). When using the GUI, the user can select the type of thresholding and can adjust the level of the threshold value. All thresholding operations was done in the image below. We can use 4 types of thresholding: - cv.THRESH_BINARY - cv.THRESH_BINARY_INV - cv.THRESH_TRUNC - cv.THRESH_TOZERO
Morphological transformations are some simple operations based on the image shape. It is normally performed on binary images. It needs two inputs, one is our original image, second one is called structuring element or kernel which decides the nature of operation. Two basic morphological operators are Erosion and Dilation. Then its variant forms like Opening, Closing, Gradient also comes into play. When using each of the transformations, the user can adjust the size of the kernel. All morphological transformations was done in the image below. Erosion The basic idea of is erode away the boundaries of foreground object. The kernel slides through the image (as in 2D convolution). A pixel in the original image (either 1 or 0) will be considered 1 only if all the pixels under the kernel is 1, otherwise it is eroded (made to zero). All the pixels near boundary will be discarded depending upon the size of kernel. So the thickness or size of the foreground object decreases or simply white region decreases in the image. It is useful for removing small white noises ordetach two connected objects etc. Erosion is done by the OpenCV function cv.erode(). Dilation It is just opposite of erosion. Here, a pixel element is '1' if at least one pixel under the kernel is '1'. So it increases the white region in the image or size of foreground object increases. For the most cases like noise removal, erosion is followed by dilation. Because, erosion removes white noises, but it also shrinks our object. It is also useful in joining broken parts of an object. Dilation is done by the OpenCV function cv.dilate(). Opening Opening is operation in which erosion is followed by dilation. It is useful in removing noise. Opening is done by the OpenCV function cv.cv.morphologyEx(). Closing Closing is reverse of Opening, Dilation followed by Erosion. It is useful in closing small holes inside the foreground objects, or small black points on the object. Closing is done by the OpenCV function cv.cv.morphologyEx(). Morphological Gradient It is the difference between dilation and erosion of an image. The result will look like the outline of the object. Morphological gradient is done by the OpenCV function cv.cv.morphologyEx(). Erosion Dilation Opening Closing Gradient
Scaling Scaling is just resizing of the image. Different interpolation methods are used. Preferable interpolation methods are cv.INTER_AREA for shrinking and cv.INTER_CUBIC (slow) & cv.INTER_LINEAR for zooming. The user can adjust the size of the image in the additional window. The effect of scaling image is presented below. Translation Translation is the shifting of object's location. If you know the shift in (x,y) direction The user can adjust the size of the shift (x, y) in the additional window. The effect of translation image is presented below. Rotation Rotation of an image for an angle θ is achieved by the transformation matrix. OpenCV provides scaled rotation with adjustable center of rotation so that you can rotate at any location you prefer. The user can adjust the size of rotation in additional window. The effect of rotate image is presented below.
In order to change the image, we use the OpenCV package function convertScaleAbs(). Changes in the brightness value can be adjusted by the user using the slider in the range of [-127, 127]. The effect of changing brightness of image is presented below.
Histogram is a graph or plot, which gives you an overall idea about the intensity distribution of an image. It is a plot with pixel values (ranging from 0 to 255) in X-axis and corresponding number of pixels in the image on Y-axis. It is used to better understand the image. By looking at the histogram of an image, you get intuition about contrast, brightness, intensity distribution etc of that image. In the interface, the user can get a histogram of the color image, each of the colors in the RGB scale is reflected by its color. In addition, it can visualize the histogram of the image in grayscale. The histograms are shown below. RGB on the left, grayscale on the right.
The following scientific resources were used in the development of the above project: