Diff of /inspection.py [000000] .. [ec4a1d]

Switch to side-by-side view

--- a
+++ b/inspection.py
@@ -0,0 +1,401 @@
+import cv2 as cv
+import numpy as np
+from matplotlib import pyplot as plt
+from statistics import stdev
+from pathlib import Path
+import datetime
+
+class Rectangle:
+    def __init__(self, x1, y1, w1, h1):
+        self.x = x1
+        self.y = y1
+        self.w = w1
+        self.h = h1
+        self.is_surface_breaking=True
+        self.is_acceptable=True
+
+    def __repr__(self):
+        return "("+str(self.x)+","+str(self.y)+"),"+str(self.w)+"x"+str(self.h)\
+               + ", Surface: " + str(self.is_surface_breaking)+", Acceptance: "+str(self.is_acceptable)
+
+
+def nothing(x):
+    print("Nothing:"+str(x))
+
+
+def is_inside_joint(inner: Rectangle, outer: Rectangle) -> bool:
+    if(inner.x >= outer.x and inner.y >= outer.y and
+            (inner.x+inner.w) <= (outer.x+outer.w) and (inner.y+inner.h) <= (outer.y+outer.h)):
+        return True
+    else:
+        return False
+
+
+def error_return():
+    return 0, 0, 0, 0, 0, 0, 0
+
+
+def find_smallest_rec(all_rec):
+
+    smallest = all_rec[0]
+    for rec in all_rec:
+        if rec.w*rec.h < smallest.w*smallest.h:
+            smallest = rec
+    return smallest
+
+
+def discard_irrelevant_results(all_recs):
+    rec_fields = []
+    rec_relevant = []
+    sum_fields = 0
+    for rec in all_recs:
+        sum_fields += rec.w*rec.h
+    average_field = sum_fields/len(all_recs)
+    # for rec in all_recs:
+    #     if rec.w * rec.h > average_field:
+    #         rec_fields.append(rec.w*rec.h)
+    #         rec_relevant.append(Rectangle(rec.x,rec.y,rec.w,rec.h))
+    for rec in all_recs:
+        rec_fields.append(rec.w * rec.h)
+
+    all_recs.remove(find_smallest_rec(all_recs))
+    deviation = stdev(rec_fields)
+    while deviation/average_field >= 0.85 and len(all_recs) > 1:
+        # print("dev/mean: "+str(deviation/average_field)+" dev: "+str(deviation)+" mean: "+str(average_field))
+        all_recs.remove(find_smallest_rec(all_recs))
+        for rec in all_recs:
+            sum_fields += rec.w*rec.h
+            rec_fields.append(rec.w*rec.h)
+        average_field = sum_fields / len(all_recs)
+        deviation = stdev(rec_fields)
+    # print("dev/mean: " + str(deviation / average_field) + " dev: " + str(deviation) + " mean: " + str(average_field))
+    # plt.hist(rec_fields, rwidth=5)
+    # plt.title("Average field: "+str(average_field)+"\nIndications: "+str(len(rec_fields)))
+    # plt.show()
+    return all_recs
+
+# def check_histograms(img, rec, roi):
+#     k=45
+#     #pobieram wymiary obrazu
+#     ref_up = cv.imread("images\\ref_up.png")
+#     ref_down = cv.imread("images\\ref_down.png")
+#     #przycinam obrazy do mierzenia histogramów
+#     indication_surface_down = img[roi.y+roi.h:roi.y+roi.h+k, rec.x:rec.x+rec.w]
+#     indication_surface_up = img[roi.y-k:roi.y, rec.x:rec.x+rec.w] #górna część obrazu oobcięta SZTYWNO
+#     #liczę histogramy
+#     hist_indication_surface_down = cv.calcHist([indication_surface_down], [0], None, [256], [0,256])
+#     hist_indication_surface_up = cv.calcHist([indication_surface_up], [0], None, [256], [0,256])
+#     hist_surface_down = cv.calcHist([ref_down], [0], None, [256], [0,256])
+#     hist_surface_up = cv.calcHist([ref_up], [0], None, [256], [0,256])
+#     #porównuję histogramy
+#     check_up = cv.compareHist(hist_surface_up, hist_indication_surface_up, cv.HISTCMP_CORREL)
+#     check_down = cv.compareHist(hist_surface_down, hist_indication_surface_down, cv.HISTCMP_CORREL)
+#     #zwracam poprawione prostokąty zależnie od histogramu
+#     # if check_down<check_up and check_down<0.92:
+#     #     corrected_rect = [(rec.x,rec.y),(rec.x+rec.w,roi.y+roi.h+k)]
+#     # elif check_up<check_down and check_up<0.92:
+#     #     corrected_rect = [(rec.x,roi.y-k),(rec.x+rec.w,rec.y+rec.h)]
+#     # else:
+#     #     corrected_rect = [(rec.x,rec.y),(rec.x+rec.w,rec.y+rec.h)]
+#     if check_down<check_up and check_down<0.15:
+#         corrected_rect = Rectangle(rec.x, rec.y, rec.w, roi.y+roi.h+k-rec.y)
+#         corrected_rect.is_surface_breaking=True
+#     elif check_up<check_down and check_up<=0.15:
+#         corrected_rect = Rectangle(rec.x, roi.y-k, rec.w, rec.y-roi.y+rec.h+k)
+#         corrected_rect.is_surface_breaking=True
+#         # [(rec.x,roi.y-k),(rec.x+rec.w,rec.y+rec.h)]
+#     else:
+#         corrected_rect = Rectangle(rec.x,rec.y,rec.w,rec.h)
+#     print("Input rec: "+str(rec))
+#     print("Check down: " + str(check_down) + "\nCheck up: " + str(check_up))
+#     print(corrected_rect)
+#
+#     return corrected_rect
+
+
+def check_histograms(img, rec, roi):
+    k = 20  # wysokość fali powierzchniowej
+
+    # pobieram wymiary obrazu
+    height, width, channels = img.shape
+    # przycinam obrazy do mierzenia histogramów
+    indication_surface_down = img[roi.y+roi.h:roi.y+roi.h+k, rec.x:rec.x+rec.w]
+    indication_surface_up = img[roi.y-k:roi.y, rec.x:rec.x+rec.w]
+    surface_down = img[roi.y+roi.h:roi.y+roi.h+k, roi.x:width]
+    surface_up = img[roi.y-k:roi.y, roi.x:width]
+    # liczę histogramy
+    hist_indication_surface_down = cv.calcHist([indication_surface_down], [0], None, [256], [0,256])
+    hist_indication_surface_up = cv.calcHist([indication_surface_up], [0], None, [256], [0,256])
+    hist_surface_down = cv.calcHist([surface_down], [0], None, [256], [0,256])
+    hist_surface_up = cv.calcHist([surface_up], [0], None, [256], [0,256])
+    # porównuję histogramy
+    check_up = cv.compareHist(hist_surface_up, hist_indication_surface_up, cv.HISTCMP_CORREL)
+    check_down = cv.compareHist(hist_surface_down, hist_indication_surface_down, cv.HISTCMP_CORREL)
+    # zwracam poprawione prostokąty zależnie od histogramu
+    # if check_down<check_up and check_down<0.92:
+    #     corrected_rect = [(rec.x,rec.y),(rec.x+rec.w,roi.y+roi.h+k)]
+    # elif check_up<check_down and check_up<0.92:
+    #     corrected_rect = [(rec.x,roi.y-k),(rec.x+rec.w,rec.y+rec.h)]
+    # else:
+    #     corrected_rect = [(rec.x,rec.y),(rec.x+rec.w,rec.y+rec.h)]
+    if check_down<check_up and check_down < 0.9:
+        corrected_rect = Rectangle(rec.x, rec.y, rec.w, roi.y+roi.h+k-rec.y)
+        corrected_rect.is_surface_breaking=True
+    elif check_up<check_down and check_up <= 0.9:
+        corrected_rect = Rectangle(rec.x, roi.y-k, rec.w, rec.y-roi.y+rec.h+k)
+        corrected_rect.is_surface_breaking = True
+        # [(rec.x,roi.y-k),(rec.x+rec.w,rec.y+rec.h)]
+    else:
+        corrected_rect = Rectangle(rec.x,rec.y,rec.w,rec.h)
+    print("Input rec: "+str(rec))
+    print("Check down: " + str(check_down) + "\nCheck up: " + str(check_up))
+    print(corrected_rect)
+
+    return corrected_rect
+
+
+def display_process(images):
+    # titles = ['ORIGINAL', 'FILTER', 'CANNY', 'DILATE', 'CONTOURS']
+    # for i in range(5):
+    #     plt.subplot(3, 2, i+1)
+    #     plt.imshow(images[i], 'gray')
+    #     plt.title(titles[i])
+    #     plt.xticks([])
+    #     plt.yticks([])
+    # plt.show()
+    plt.subplot(1, 2, 1)
+    plt.imshow(images[1], 'gray')
+    plt.title('FILTER')
+    plt.xticks([])
+    plt.yticks([])
+    plt.subplot(1,2,2)
+    plt.imshow(images[2], 'gray')
+    plt.title('EDGES')
+    plt.xticks([])
+    plt.yticks([])
+    plt.show()
+
+
+def find_roi(filename):
+
+    thresh1 = 100
+    thresh2 = 255
+    dil_kernel_size = 7
+    dil_it = 3
+    filter_kernel = 5
+
+    roi_img = cv.imread(filename)
+    roi_imgray = cv.cvtColor(roi_img, cv.COLOR_BGR2GRAY)
+    roi_imgray=cv.GaussianBlur(roi_imgray,(filter_kernel,filter_kernel),0)
+    _, roi_imthresh = cv.threshold(roi_imgray, thresh1, thresh2, cv.THRESH_BINARY_INV)
+    roi_kernel = np.ones((dil_kernel_size, dil_kernel_size), np.uint8)
+    roi_imdil = cv.dilate(roi_imthresh, roi_kernel, iterations=dil_it)
+
+    h, w, c = roi_img.shape
+    roi_mat_img = np.transpose(roi_imdil)
+    first_column = roi_mat_img[0]
+
+    for i in range(len(first_column)):
+        if i == len(first_column)-1:
+            y_min = 0
+            y_max = len(first_column)-1
+            break
+        if first_column[i] == 255 and first_column[i + 1] == 0 and i > 10:
+            y_min = i
+            break
+
+    for j in range(i, len(first_column) - 1):
+        if first_column[j] == 0 and first_column[j + 1] == 255 and j - y_min > 50:
+            y_max = j
+            break
+
+    roi = Rectangle(0, y_min, w, y_max-y_min)
+    return roi
+
+
+def convert_to_mm(roi, thickness, all_recs):
+    px_to_mm = int(thickness)/(roi.h+60)
+    all_recs_in_mm = []
+    for rec in all_recs:
+        rec_in_mm = Rectangle(round(rec.x*px_to_mm, 1), round(rec.y*px_to_mm, 1),
+                              round(rec.w*px_to_mm, 1), round(rec.h*px_to_mm, 1))
+        all_recs_in_mm.append(rec_in_mm)
+
+    x_max = 0; y_max = 0; w_max = 0; h_max = 0
+
+    for rec in all_recs_in_mm:
+        if rec.w * rec.h > w_max * h_max:
+            x_max = rec.x
+            y_max = rec.y
+            w_max = rec.w
+            h_max = rec.h
+
+    return x_max, y_max, w_max, h_max, all_recs_in_mm
+
+
+def confirm_indications(all_indications, acceptance_level, thickness):
+    joint_acceptance = True
+    if acceptance_level == 1:
+        l_max = 0.75*float(thickness)
+        h3 = 1.5
+        h2 = 2
+        h1 = 1
+    elif acceptance_level == 2:
+        l_max = thickness
+        h3 = 2
+        h2 = 2
+        h1 = 1
+    elif acceptance_level == 3:
+        l_max = min(1.5*thickness, 20)
+        h3 = 2
+        h2 = 2
+        h1 = 1
+
+    for ind in all_indications:
+        if ind.w > l_max and ind.h > h1:
+            ind.is_acceptable = False
+            joint_acceptance = False
+        elif ind.w <= l_max:
+            if ind.is_surface_breaking and ind.h > h3:
+                ind.is_acceptable = False
+                joint_acceptance = False
+            elif not ind.is_surface_breaking and ind.h > h2:
+                ind.is_acceptable = False
+                joint_acceptance = False
+        elif ind.h < h2 or ind.h < h3:
+            if ind.w > l_max:
+                ind.is_acceptable = False
+                joint_acceptance = False
+
+    for ind in all_indications:
+        print(ind)
+
+    date = datetime.date.today()
+    time = datetime.datetime.now().time()
+
+    with open(str(date) + "_" + str(time).replace(':', '_')[:-8] + "_results.txt", "w") as f:
+        i = 0
+        for rec in all_indications:
+            f.write("Pattern " + str(i) + ": x0 = " + str(rec.x) + "; y0 = " + str(rec.y) + "; w = "
+                    + str(rec.w) + "; h = " + str(rec.h) + "; " + str(rec.is_acceptable) + "\n")
+            i += 1
+
+    return joint_acceptance
+
+
+def inspect(filepath, list_of_parameters, acceptance_level, thickness):
+    try:
+        filter_size=list_of_parameters[0]
+        canny_min=list_of_parameters[1]
+        canny_max=list_of_parameters[2]
+        dilation_kernel_size=list_of_parameters[3]
+        dilation_it=list_of_parameters[4]
+        roi_x_min=list_of_parameters[5]
+        roi_x_max=list_of_parameters[6]
+        roi_y_min=list_of_parameters[7]
+        roi_y_max=list_of_parameters[8]
+
+    except IndexError:
+        filter_size = 9
+        canny_min = 20
+        canny_max = 77
+        dilation_kernel_size = 3
+        dilation_it = 3
+        roi_x_min = -1
+        roi_x_max = -1
+        roi_y_min = -1
+        roi_y_max = -1
+
+    try_file = cv.imread(filepath)
+    try:
+        try_file.size == 0
+    except AttributeError:
+        return error_return()
+
+    if roi_x_min == -1 and roi_x_max == -1 and roi_y_min == -1 and roi_y_max == -1:
+        roi = find_roi(filepath)
+    else:
+        roi = Rectangle(roi_x_min, roi_y_min, roi_x_max-roi_x_min, roi_y_max-roi_y_min)
+
+
+    img = cv.imread(filepath)
+    height, width, channels = img.shape
+    imgray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
+
+    filter_img = cv.medianBlur(imgray,filter_size)
+    # filter_img = cv.GaussianBlur(imgray,(filter_size,filter_size),0)
+    # filter_img = cv.bilateralFilter(imgray, 10, 10, 10)
+
+    edges = cv.Canny(filter_img, canny_min, canny_max)
+    cv.imwrite("edges.png", edges)
+
+    try:
+        img_to_dilate = edges[roi.y:roi.y+roi.h, roi.x:roi.x+roi.w]
+    except IndexError:
+        return error_return()
+
+    kernel = np.ones((dilation_kernel_size, dilation_kernel_size), np.uint8)
+
+    img_to_dilate = cv.dilate(img_to_dilate, kernel, iterations=dilation_it)
+    edges[roi.y:roi.y+roi.h,roi.x:roi.x+roi.w] = cv.morphologyEx(img_to_dilate, cv.MORPH_CLOSE, kernel)
+    dilation = cv.morphologyEx(edges, cv.MORPH_ERODE, kernel)
+
+    contours, hierarchy = cv.findContours(dilation, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
+    number_of_recs=0
+    all_recs = []
+    for i in range(len(contours)):
+        x, y, w, h = cv.boundingRect(contours[i])
+        rec = Rectangle(x, y, w, h)
+        if is_inside_joint(rec, roi):
+            cv.drawContours(img, contours, i, (0, 0, 255), 1)
+            all_recs.append(rec)
+            number_of_recs += 1
+
+    if len(all_recs) == 0:
+        return error_return()
+
+    cv.imwrite("contours.png",img)
+    filtered_recs = discard_irrelevant_results(all_recs)
+    corrected_recs = filtered_recs
+    if len(corrected_recs) == 0:
+        return error_return()
+
+    # corrected_recs = []
+    # for rec in filtered_recs:
+    #     corrected_recs.append(check_histograms(img, rec, roi))
+
+    x_max = 0; y_max = 0; w_max = 0; h_max = 0
+    for rec in corrected_recs:
+        cv.rectangle(img, (rec.x, rec.y), (rec.x + rec.w, rec.y + rec.h), (0, 255, 0), 1)
+        if rec.w * rec.h > w_max * h_max:
+            x_max = rec.x
+            y_max = rec.y
+            w_max = rec.w
+            h_max = rec.h
+
+    images = [imgray, filter_img, edges, dilation, img]
+    filepath_inspected = filepath.replace(".png", "_inspected.png")
+    cv.imwrite(filepath_inspected, img)
+
+    x_max, y_max, w_max, h_max, all_recs_in_mm = convert_to_mm(roi, thickness, corrected_recs)
+    acceptance = confirm_indications(all_recs_in_mm, acceptance_level, thickness)
+
+    with open(Path(filepath).stem+"_results_in_pixels.txt", "w") as f:
+        i = 0
+        for rec in all_recs:
+
+            f.write("Pattern " + str(i) + ": x0 = " + str(rec.x) + "; y0 = " + str(rec.y) + "; w = " +
+                    str(rec.w) + "; h = " + str(rec.h) + "\n")
+            i += 1
+
+    return acceptance, x_max, y_max, w_max, h_max, filepath_inspected, images
+
+
+#throwMe = [9, 20, 77, 3, 3, -1, -1, -1, -1]
+#acc, x_max, y_max, w_max, h_max, filepath_inspected, images = inspect("images\\test1.png", throwMe, 3, 12)
+#cv.imshow("result", images[0])
+#cv.waitKey()
+#cv.destroyAllWindows()
+
+# pierwsza strona do podpisu, reszta mailem, prezka w grudniu mailem i przyjść przegadać
+#
\ No newline at end of file