Advertisement
dan-masek

Untitled

Sep 18th, 2018
322
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.93 KB | None | 0 0
  1. import cv2
  2. import numpy as np
  3. import glob
  4. import math
  5.  
  6. import StringIO
  7.  
  8. from scipy.signal import argrelmax, find_peaks
  9.  
  10. # ============================================================================
  11.  
  12. zones_a = [(50, 72), (144, 166), (243, 265), (328, 350), (436, 458)]
  13. zones_b = [(42,  64), (122, 144), (207, 229), (276, 298), (369, 391), (496, 518)]
  14.  
  15. # ============================================================================
  16.  
  17. def plot_report(filename, report):
  18.     from matplotlib import pyplot as plt
  19.     from matplotlib.gridspec import GridSpec
  20.    
  21.     IMAGE_KEYS = ['img', 'thresh', 'thresh_1', 'thresh_2', 'canny', 'canny_1', 'canny_2']
  22.     PLOT_SPAN = 5
  23.     TEXT_SPAN = 2
  24.     ROW_COUNT = (len(IMAGE_KEYS) + 1) + 3 * (PLOT_SPAN + 1) + 2 * (TEXT_SPAN)
  25.    
  26.     fig = plt.figure()
  27.     plt.suptitle(filename)
  28.     gs = GridSpec(ROW_COUNT, 2)
  29.    
  30.     row = 0
  31.  
  32.     for key in IMAGE_KEYS:
  33.         plt.subplot(gs[row,:])
  34.         plt.gca().set_title(key)
  35.         plt.imshow(report[key], cmap='gray', aspect='equal')
  36.         plt.axis('off')
  37.         row += 1
  38.    
  39.     proj_width = len(report['projection'])
  40.     proj_x = np.arange(proj_width)
  41.    
  42.     plt.subplot(gs[row+1:row+1+PLOT_SPAN,:])
  43.     plt.gca().set_title('Vertical Projections (Raw and Smoothed)')
  44.     plt.plot(proj_x, report['projection'], 'y-')
  45.     plt.plot(proj_x, report['projection_1'], 'r-')
  46.     plt.plot(proj_x, report['projection_2'], 'b-')
  47.     plt.xlim((0, proj_width - 1))
  48.     plt.ylim((0, 255))
  49.    
  50.     row += PLOT_SPAN + 1
  51.    
  52.     #bins_ab, weight_ab, details_ab, checkbox_count
  53.    
  54.     plt.subplot(gs[row+1:row+1+PLOT_SPAN,:])
  55.     plt.gca().set_title('Smoothed Projection with Peaks and Zones')
  56.     plt.plot(proj_x, report['projection_2'])
  57.        
  58.     for zone in zones_a:
  59.         plt.axvspan(zone[0], zone[1], facecolor='y', alpha=0.1)
  60.     for zone in zones_b:
  61.         plt.axvspan(zone[0], zone[1], facecolor='r', alpha=0.1)
  62.     for x in report['peaks']:
  63.         plt.axvline(x=x, color='m')
  64.        
  65.     plt.xlim((0, proj_width - 1))
  66.     plt.ylim((0, report['projection_2'].max()))
  67.        
  68.     row += PLOT_SPAN + 1
  69.  
  70.     plt.subplot(gs[row+1:row+1+TEXT_SPAN,0], frameon=False)
  71.     plt.gca().set_title('Details - 5 boxes')
  72.     plt.axis([0, 1, 0, 1])
  73.     plt.gca().axes.get_yaxis().set_visible(False)
  74.     plt.gca().axes.get_xaxis().set_visible(False)
  75.     plt.text(0, 1, report['details_a'], family='monospace', fontsize=8, ha='left', va='top')
  76.    
  77.     plt.subplot(gs[row+1:row+1+TEXT_SPAN,1], frameon=False)
  78.     plt.gca().set_title('Details - 6 boxes')
  79.     plt.axis([0, 1, 0, 1])
  80.     plt.gca().axes.get_yaxis().set_visible(False)
  81.     plt.gca().axes.get_xaxis().set_visible(False)
  82.     plt.text(0, 1, report['details_b'], family='monospace', fontsize=8, ha='left', va='top')    
  83.    
  84.     row += TEXT_SPAN
  85.    
  86.     plt.subplot(gs[row+1:row+1+PLOT_SPAN,:])
  87.     plt.gca().set_title('Weights')
  88.     plt.barh([2, 1]
  89.         , [report['weight_a'], report['weight_b']]
  90.         , align='center'
  91.         , color=['y', 'r']
  92.         , tick_label=['5 boxes', '6 boxes'])
  93.     plt.ylim((0.5, 2.5))
  94.    
  95.     row += PLOT_SPAN + 1
  96.     row += 1
  97.    
  98.     plt.subplot(gs[row,:])
  99.     plt.gca().set_title('Input Image')
  100.     plt.imshow(report['img'], cmap='gray', aspect='equal')
  101.     plt.axis('off')
  102.    
  103.     row += 1
  104.    
  105.     plt.subplot(gs[row:row+TEXT_SPAN,:], frameon=False)
  106.     plt.axis([0, 1, 0, 1])
  107.     plt.gca().axes.get_yaxis().set_visible(False)
  108.     plt.gca().axes.get_xaxis().set_visible(False)
  109.     result_text = "The image contains %d boxes." % report['checkbox_count']
  110.     plt.text(0.5, 1, result_text, family='monospace', weight='semibold', fontsize=24, ha='center', va='top')  
  111.        
  112.     fig.set_size_inches(12, ROW_COUNT * 0.8)
  113.     plt.savefig('plot_%s.png' % filename[:2], bbox_inches="tight")
  114.     plt.close(fig)
  115.    
  116.    
  117. def bin_peaks(peaks, values, zones):
  118.     bins = [[] for x in xrange(len(zones))]
  119.    
  120.     for peak, value in zip(peaks, values):
  121.         for i, zone in enumerate(zones):
  122.             if (peak >= zone[0]) and (peak <= zone[1]):
  123.                 bins[i].append((peak, value))
  124.    
  125.     return bins
  126.    
  127. def analyze_bins(bins):
  128.     buf = StringIO.StringIO()
  129.    
  130.     total_weight = 0.0
  131.     for i, bin in enumerate(bins):
  132.         buf.write("Position %d: " % i)
  133.         weight = 0.0
  134.         if len(bin) == 0:
  135.             buf.write("no peaks")
  136.         else:
  137.             best_bin = sorted(bin, key=lambda x: x[1], reverse=True)[0]
  138.             weight = best_bin[1]
  139.             if len(bin) == 1:
  140.                 buf.write("single peak @ %d (value=%0.3f)" % best_bin)
  141.             else:
  142.                 buf.write("%d peaks, best @ %d (value=%0.3f)" % (len(bin), best_bin[0], best_bin[1]))
  143.            
  144.         buf.write(" | weight=%0.3f\n" % weight)
  145.        
  146.         total_weight += weight
  147.        
  148.     buf.write("Total weight = %0.3f" % total_weight)
  149.     return total_weight, buf.getvalue()
  150.  
  151.    
  152. def proc(filename):
  153.     report = {}
  154.  
  155.     img = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
  156.     report['img'] = img.copy()
  157.    
  158.     thresh = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 15, 2)
  159.     report['thresh'] = thresh.copy()
  160.    
  161.     thresh = cv2.morphologyEx(thresh, cv2.MORPH_ERODE, np.ones((1,3),np.uint8))
  162.     report['thresh_1'] = thresh.copy()
  163.    
  164.     thresh = cv2.morphologyEx(thresh, cv2.MORPH_DILATE, np.ones((3,1),np.uint8))
  165.     report['thresh_2'] = thresh.copy()
  166.    
  167.     edges = cv2.Canny(thresh, 40, 120, apertureSize=5)
  168.     report['canny'] = edges.copy()
  169.    
  170.     edges = cv2.morphologyEx(edges, cv2.MORPH_OPEN, np.ones((5,1),np.uint8))
  171.     report['canny_1'] = edges.copy()
  172.    
  173.     edges = cv2.morphologyEx(edges, cv2.MORPH_DILATE, np.ones((1,3),np.uint8))
  174.     report['canny_2'] = edges.copy()
  175.    
  176.     projection = np.mean(edges, 0).flatten()
  177.     report['projection'] = projection.copy()
  178.    
  179.     projection = cv2.blur(projection, (1, 21)).flatten()
  180.     report['projection_1'] = projection.copy()
  181.    
  182.     projection = cv2.blur(projection, (1, 11)).flatten()
  183.     report['projection_2'] = projection.copy()
  184.    
  185.     peaks = find_peaks(projection)[0]
  186.     report['peaks'] = peaks.copy()
  187.    
  188.     peak_values = projection[peaks]
  189.     report['peak_values'] = peak_values.copy()
  190.    
  191.     bins_a = bin_peaks(peaks, peak_values, zones_a)
  192.     report['bins_a'] = list(bins_a)
  193.    
  194.     bins_b = bin_peaks(peaks, peak_values, zones_b)
  195.     report['bins_b'] = list(bins_b)
  196.  
  197.     weight_a, details_a = analyze_bins(bins_a)
  198.     report['weight_a'] = weight_a
  199.     report['details_a'] = details_a
  200.     weight_b, details_b = analyze_bins(bins_b)
  201.     report['weight_b'] = weight_b
  202.     report['details_b'] = details_b
  203.  
  204.     checkbox_count = 5 if (weight_a > weight_b) else 6
  205.     report['checkbox_count'] = checkbox_count
  206.  
  207.     return checkbox_count, report
  208.    
  209.  
  210. for filename in glob.glob('*-*.png'):
  211.     box_count, report = proc(filename)
  212.     plot_report(filename, report)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement