Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save stefanherdy/ccdd19669684f9a85b64542e33a972aa to your computer and use it in GitHub Desktop.
Save stefanherdy/ccdd19669684f9a85b64542e33a972aa to your computer and use it in GitHub Desktop.
This script iterates through a folder and performs an edge detection to all jpg and png-images in the folder. The function was used to monitor the additive manufacturing of steel and titanium parts (selective laser sintering). During the manufactoring process, the images were analysed and anomalies in the powder bed of the 3D printing machine we…
#!/usr/bin/env python3
"""
Script Name: python_edge_detection_for_quality_inspection.py
Author: Stefan Herdy
Date: 18.08.2019
Description:
This script iterates through a folder and performs an edge detection to all jpg and png-images in the folder.
The provided function was used to monitor the additive manufacturing of steel and titanium parts (selective laser sintering).
During the manufactoring process, the images were analysed and anomalies in the powder bed of the 3D printing machine were detected.
Usage:
- Set your own function parameters for edge detection etc.
- Set your data path
- Import the script and execute the provided function
"""
from imutils import contours
from skimage import measure
import numpy as np
import argparse
import PIL
import imutils
import cv2
from os import listdir
import sys
from PIL import Image
#from torchvision import transforms
#import torchvision
import shutil
import tkinter
import random
import os
import sqlite3
import matplotlib.pyplot as plt
from tkinter.ttk import Progressbar
def detect_image_anomalies(path, low_thresh, high_thresh, area_thresh, g_size, cr_num):
if not os.path.exists(path):
tkinter.messagebox.showerror("Error", "Path does not exist!")
cfiles = listdir(path)
files = listdir(path)
if not files:
tkinter.messagebox.showerror("Error", "No files in the directory")
f = random.choice(cfiles)
# init arrays to store results of the egde detection
elist = []
rlist = []
rad = 0
pro = 1
text = " "
progressm = tkinter.Tk()
progressm.title("Progress")
progressl = tkinter.Label(progressm, text=text, width=25)
progress = Progressbar(progressm, orient="horizontal", length=100, mode='determinate')
images = [x for x in files if x.endswith(('jpg', 'png'))]
for img in images:
progressl["text"] = "Analysed:" + str(pro) + "of" + str(int(len(files)))
progressl.pack()
progress.pack()
progress['value'] = pro / (len(files)/2) * 100
#fr1.update_idletasks()
progress.update_idletasks()
progressl.pack()
progressl.update_idletasks()
# load the image, convert it to grayscale, and blur it
dir = os.path.join(path, img)
image = cv2.imread(dir, 0)
# The Canny function does a blurr. Blurring the image first could still improve the quality of the analysis.
blurred = cv2.GaussianBlur(image, (g_size, g_size), 0)
# cv2.imshow("blurr", blurred)
canny = cv2.Canny(blurred, low_thresh, high_thresh)
## You can also perform erosion and dilation on your own:
# perform a series of erosions and dilations to remove
# any small blobs of noise from the thresholded image
kernel = np.ones((3, 3))
# image = cv2.erode(image, kernel, iterations=1)
# image = cv2.dilate(image, None, iterations=4)
# perform a connected component analysis on the thresholded
# image, then initialize a mask to store only the "large"
# components
labels = measure.label(canny, neighbors=8, background=0)
mask = np.zeros(canny.shape, dtype="uint8")
# loop over the unique components
for label in np.unique(labels):
# if this is the background label, ignore it
if label == 0:
continue
# otherwise, construct the label mask and count the
# number of pixels
labelMask = np.zeros(canny.shape, dtype="uint8")
labelMask[labels == label] = 255
numPixels = cv2.countNonZero(labelMask)
# if the number of pixels in the component is sufficiently
# large, then add it to our mask of "large blobs"
if numPixels > area_thresh:
mask = cv2.add(mask, labelMask)
# find the contours in the mask, then sort them from left to
# right
cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
if cnts == True:
cnts = contours.sort_contours(cnts)[0]
rad = 0
# loop over the contours
for (i, c) in enumerate(cnts):
# print(c)
maxlist = []
# draw the bright spot on the image
(x1, y1, w1, h1) = cv2.boundingRect(c)
((cX, cY), radius) = cv2.minEnclosingCircle(c)
cv2.circle(image, (int(cX), int(cY)), int(radius),
(255, 255, 255), 1)
cv2.putText(image, "#{}".format(i + 1), (x1, y1 - 15),
cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 1)
maxlist.append(radius)
try:
rad = max(maxlist)
except:
rad = 0
rlist.append(rad)
elist.append(len(cnts))
# show the output image
name = str(img)
if len(cnts) > cr_num:
cv2.namedWindow(name)
cv2.moveWindow(name, 100, 100)
cv2.imshow(name, image)
cv2.waitKey(0)
cv2.destroyWindow(name)
pro +=1
return elist
# set low and high threshold for Canny Edge detection
low_thresh = 75
high_thresh = 180
# Set threshold for the minimun area of the detected anomalies
area_thresh = 70
# Spezify kernel size for gaussian blurr
g_size = 11
# Set critical number of counts, where image is shown or not
cr_num = 0
# Set data path
path = 'C:/Users/stefa/Pictures/Camera Roll/'
if __name__ == "__main__":
detect_image_anomalies(path, low_thresh, high_thresh, area_thresh, g_size, cr_num)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment