In [1]:
%matplotlib inline
import numpy as np
import cv2
import cv
import matplotlib.pyplot as plt
import os
from IPython.html.widgets import interact, interactive, fixed
from IPython.display import clear_output, display, HTML
from IPython.html import widgets
from collections import Counter
from matplotlib import pyplot as plt
In [2]:
from io import BytesIO
import PIL
from IPython.display import display, Image

def display_img_array(ima, cvt=cv2.COLOR_BGR2RGB, **kwargs):
    if cvt:
        ima = cv2.cvtColor(ima, cvt)
    im = PIL.Image.fromarray(ima)
    bio = BytesIO()
    im.save(bio, format='png')
    display(Image(bio.getvalue(), format='png', **kwargs))
In [ ]:
%qtconsole --colors=linux
In [ ]:
from random import randint
def sim(c1, c2, D=80):
    return sum(abs(int(c1[k])-int(c2[k])) for k in range(3))<=D
imgs = [cv2.imread('img/rail{}.jpg'.format(i)) for i in range(10)]
for img in imgs:
    display_img_array(img, width=600)
    z = iter(img.flatten())
    mcolor = np.array(Counter(zip(z,z,z)).most_common(1)[0][0], dtype=np.float32)
    h,w,c = img.shape
    for i in range(h):
        for j in range(w):
            if sim(mcolor, img[i,j],65):
                img[i,j]=(0,0,0)            
    fimg = img.reshape((-1,3)).astype(dtype=np.float32)
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
    K = 7
    ret,label,center=cv2.kmeans(fimg,K, criteria,10, cv2.KMEANS_RANDOM_CENTERS)
    """
    plt.scatter(fimg[:,0], fimg[:,1])
    plt.scatter(center[:,0], center[:,1],  s=80, c='r')
    plt.axis([0,256]*2)
    plt.show()
    """
    nimg = center.astype(np.uint8)[label.flatten()].reshape(img.shape)
    random_color = np.array([[randint(0,255) for j in range(3)] for i in range(K+1)], dtype=np.uint8)
    nimg2 = random_color[label.flatten()].reshape(img.shape)        
    #display_img_array(nimg, width=600)
    #display_img_array(nimg2, width=600)

    def remove_hline(img, img2, i,j):
        if img[i,j] in (img[i-1,j], img[i+1,j]):
            return        
        if img[i, j-1] == img[i, j+1] == img[i-1, j] == img[i+1,j]:
            img2[i,j]= img[i, j-1]
            return
        j1=j
        #while j1>=0 and img[i,j1] not in (0,K,img[i-1,j1],img[i+1,j1]):
        while j1>=0 and img[i,j1]!=img[i-1,j1] and img[i-1,j1] ==  img[i+1,j1]:
            j1-=1
        j1+=1
        j2 = j
        while j2<img.shape[1] and  img[i,j2]!=img[i-1,j2] and img[i-1,j2] == img[i+1,j2]:
            j2+=1
        if j2-j1 >=4:
            for j0 in range(j1,j2):
                img2[i,j0]=img[i-1,j0]
    icenter = map(tuple, center.astype(np.uint8))
    zero = icenter.index((0,0,0))
    print "zero", zero
    
    def remove_vline(img, img2,  i,j):
        if img[i,j] in (img[i,j-1], img[i,j+1]):
            return
        if img[i, j-1] == img[i, j+1] == img[i-1, j] == img[i+1,j]:
            img2[i,j]= img[i, j-1]
            return
        i1=i
        while i1>=0 and img[i1,j]!=img[i1,j-1] and img[i1,j-1] == img[i1,j+1]:
            i1-=1
        i1+=1
        i2 = i
        #while i2<img.shape[0] and  img[i2,j] not in (zero,K, img[i2,j-1], img[i2,j+1]):
        while i2<img.shape[0] and  img[i2,j]!=img[i2,j-1] and img[i2,j-1]==img[i2,j+1]:
            i2+=1
        if i2-i1 >=4:
            for i0 in range(i1,i2):
                img2[i0,j]=img[i0,j-1]
    limg = label.reshape(img.shape[:2])
    for iterate in range(2):
        limg2 = limg.copy()
        for i in range(1,h-1):
            for j in range(1,w-1):
                remove_vline(limg, limg2, i,j)
                remove_hline(limg, limg2, i, j)                
        limg = limg2
    bw=np.array([255 if i !=zero else 0 for i in range(K)], dtype=np.uint8)
    nimg3 = bw[limg2.flatten()].reshape(img.shape[:2])    
    display_img_array(nimg3, None, width=600)
In [ ]:
def sim(c1, c2):
    return sum(abs(int(c1[k])-int(c2[k])) for k in range(3))<=80
        
def find_line(img,i,j):    
    L=5
    for j2 in range(j, j+4):
        if not sim(img[i,j2], img[i,j2+1]):
            return False
        if sim(img[i,j2], img[i-1,j2]) or sim(img[i,j2], img[i+1,j2]):
            return False
    return True

def find_vline(img,i,j):    
    L=5
    for i2 in range(i, i+4):
        if not sim(img[i2,j], img[i2+1,j]):
            return False
        if sim(img[i2,j], img[i2,j-1]) or sim(img[i2,j], img[i2,j+1]):
            return False
    return True
                    
imgs = [cv2.imread('img/rail{}.jpg'.format(i)) for i in range(10)]        
    
for img in imgs:
    display_img_array(img)
    z = iter(img.flatten())
    mcolor = np.array(Counter(zip(z,z,z)).most_common(1)[0][0], dtype=np.float32)
    h,w,c = img.shape
    nimg = np.zeros_like(img)
    for i in range(1,h-5):
        for j in range(1,w-5):
            nimg[i,j]=img[i,j]
            if (abs(img[i,j]-mcolor)).max() >30:
                if  find_line(img, i, j):
                    nimg[i,j]=(0,255,0)
                elif  find_vline(img, i, j):
                    nimg[i,j]=(0,255,0)
                else:
                    nimg[i,j]=img[i,j]
                    #nimg[i,j]=img[i-1,j]
                    #(img[i+1,j].astype(np.uint32)+img[i-1,j].astype(np.uint32))/2
       
    display_img_array(nimg)
In [ ]:
def good_point(img,i,j):
    for k in range(3):
        v=[img[i,j,k], img[i+1,j+1,k], img[i+1,j-1,k], img[i-1,j-1,k], img[i-1,j+1,k]]
        v = map(int, v)
        if max(v)-min(v) > 30:
            return False
    return True

def good_nbhd(img, i0, j0):
    color = img[i0,j0]
    pts= {(i0,j0)}
    newpts = {(i0,j0)}
    while newpts:
        newpts2 = set()
        for pt in newpts:
            for i in range(pt[0]-2, pt[0]+3):
                if i<0 or i >= img.shape[0]:
                    continue
                for j in range(pt[1]-2, pt[1]+3):
                    if j < 0 or j >=img.shape[1]:
                        continue
                    if (i,j) in pts:
                        continue
                    color2 = img[i,j]
                    if max(abs(int(color[k])-int(color2[k])) for k in range(3)) <=15:
                        newpts2.add((i,j))
                        pts.add((i,j))
        newpts = newpts2
    return pts
                    
imgs = [cv2.imread('img/rail{}.jpg'.format(i)) for i in range(10)]        
    
for img in imgs[:1]:
    display_img_array(img)
    z = iter(img.flatten())
    mcolor = np.array(Counter(zip(z,z,z)).most_common(1)[0][0], dtype=np.float32)
    h,w,c = img.shape
    nimg = np.zeros_like(img)
    for pt in good_nbhd(img,28,12):
            nimg[pt[0],pt[1]]=(128,0,128)
    nimg[30,10]=(255,255,255)
    display_img_array(nimg)
    """
    for i in range(1,h-5):
        for j in range(1,w-5):
            if (abs(img[i,j]-mcolor)).max() >30:
                if True or good_rect(img, i, j):
                    #nimg[i,j]=(255,255,255) 
                    #print i,j, len(good_nbhd(img,i,j))
                    for pt in good_nbhd(img,i,j):
                        #if tuple(nimg[pt[0],pt[1]]) in [(0,0,0), (0,128,0)]:                        
                            nimg[pt[0],pt[1]]=(128,0,128)
                    break
                else:
                    if tuple(nimg[i,j]) == (0,0,0):
                        nimg[i,j]=(0,128,0)
    display_img_array(nimg)
"""    
In [ ]:
imgs = [cv2.cvtColor(cv2.imread('img/rail{}.jpg'.format(i)), cv2.COLOR_BGR2GRAY ) for i in range(10)]
for img in imgs:
    display_img_array(img, None)
In [ ]:
# Find key points
#orb = cv2.ORB()
sift = cv2.SIFT()
img1 = imgs[3]
img2 = imgs[5]
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)
k1 = cv2.drawKeypoints(img1, kp1)
display_img_array(k1)
k2 = cv2.drawKeypoints(img2, kp2)
display_img_array(k2)
In [ ]:
# Match Key points
if 0: # Brute Force Match
    #bf = cv2.BFMatcher(cv2.NORM_HAMMING) #, crossCheck=True)
    bf = cv2.BFMatcher(cv2.NORM_L2) #, crossCheck=True)
    matches = bf.knnMatch(des1, des2, k=2)
else: #Flann Match
    index_params= dict(algorithm = 0, tree=5)
    search_params = dict(checks=50) 
    flann = cv2.FlannBasedMatcher(index_params, search_params)
    matches = flann.knnMatch(des1, des2, k=2)
In [ ]:
# Draw Matches
H1, W1 = img1.shape[:2]
slide_h, slide_w = H2,W2 = img2.shape[:2]
#print img.shape, frame.shape
from random import randint
_img2 = cv2.resize(img2, ( 800, H2*800/W2))
NH1 = H1*800/W1
_img1 = cv2.resize(img1, (800, NH1))
outimg = np.concatenate((_img1, _img2), axis=0)
def draw_match_line(pt1, pt2):
    draw1(pt1)
    draw2(pt2)
    pt1 = pt1[0]*800/W1, pt1[1]*800/W1
    pt2 = pt2[0]*800/W2, pt2[1]*800/W2+NH1
    poly =  [pt1, pt2]
    cv2.polylines(outimg, np.int32([poly]), True, (randint(0,255), randint(0,255), randint(0,255)), 1)
def draw1(pt):
    pt = np.float32(pt)*800/W1
    pt = tuple(np.int32(pt))
    cv2.circle(outimg, pt, 3, (0,0,255))
def draw2(pt2):
    pt2 = int(pt2[0]*800/W2), int(pt2[1]*800/W2+NH1)
    cv2.circle(outimg, pt2, 3, (0,0,255))
    #cv2.polylines(outimg, np.int32([poly]), True, (0,255,255), 3)
m2 = []
for x in matches:
    #if len(x)==2 and x[0].distance> 0.6*x[1].distance:
    #    continue
    if len(x)==0:
        continue
    m2.append(x[0])
m2.sort(key=lambda x:x.distance)
for x in m2[:20]:
    #print x.queryIdx, x.trainIdx
    pt1 = kp1[x.queryIdx].pt
    pt2 = kp2[x.trainIdx].pt
    # print kp1[x.queryIdx].angle,  kp2[x.trainIdx].angle
    print pt1, pt2    
    draw_match_line(pt1,pt2)
display_img_array(outimg, cvt=None)
In [ ]:
imgs = [cv2.cvtColor(cv2.imread('img/rail{}.jpg'.format(i)), cv2.COLOR_BGR2GRAY ) for i in range(10)]
for img in imgs:
    display_img_array(img, None)
    thresh = cv2.adaptiveThreshold(img,  255, 
                                                  cv2.ADAPTIVE_THRESH_MEAN_C, 
                                                  cv2.THRESH_BINARY, 
                                                  11, 
                                                  -5.0)
    display_img_array(thresh, None)
    ret,thresh = cv2.threshold(img, 110,255, cv2.THRESH_BINARY_INV)
    #display_img_array(thresh, None)
    #ret,thresh = cv2.threshold(thresh, 30,255, cv2.THRESH_TOZERO)
    contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
    im = np.zeros_like(img)
    cv2.drawContours(im,contours,-1,255,1)    
    #display_img_array(im, None)
In [ ]:
%qtconsole --colors=linux
In [ ]:
imgs = [cv2.imread('img/rail{}.jpg'.format(i)) for i in range(10)]
from collections import Counter
for img in imgs:
    z = iter(img.flatten())
    mcolor = np.array(Counter(zip(z,z,z)).most_common(1)[0][0], dtype=np.float32)-128.0
    mv = mcolor / np.linalg.norm(mcolor)
    print mv
    #nimg = abs((img - np.kron(np.dot(img, mv), mv).reshape(60,200,3))).astype(np.uint8)
    #nimg = cv2.cvtColor(nimg, cv2.COLOR_BGR2GRAY)
    #ret,thresh = cv2.threshold(nimg, 10,255, cv2.THRESH_BINARY_INV)
    h,w,c = img.shape
    nimg = np.zeros((h,w), dtype=np.uint8)
    print h,w,c,nimg.shape
    display_img_array(img)
    for i in range(h):
        for j in range(w):
            v = img[i,j].astype(np.float32)-128.0
            n = np.linalg.norm(v)    
            r = np.dot(v,mv)/n
            if all(v[i]>=mcolor[i]+5 for i in range(3)):
                nimg[i,j] = 255
            else:
                nimg[i,j]= 0
            #2000*(r-0.9)
            #0 if n ==0 else 200*r
    #nimg = np.array([[img[i,j]-np.dot(img[i,j],mv)*mv for j in range(w)] for i in range(h)], dtype=np.uint8)
    print nimg.min(), nimg.max()
    display_img_array(nimg, None)
    

    
In [165]:
from skimage import morphology
import skimage
imgs = [cv2.imread('img/rail{}.jpg'.format(i)) for i in range(20)]
for img in imgs:
    display_img_array(img, width=600)
    z = iter(img.flatten())
    mcolor = np.array(Counter(zip(z,z,z)).most_common(1)[0][0], dtype=np.float32)
    h,w,c = img.shape
    nimg=np.zeros((h,w,c), dtype=np.uint8)
    for i in range(h):
        for j in range(w):
            #nimg[i,j]=abs(img[i,j]-mcolor).astype(dtype=np.uint8)
            if sim(mcolor, img[i,j], 120):
                nimg[i,j]=(0,0,0)
            else:
                nimg[i,j]=img[i,j]
    display_img_array(nimg, width=600)
    z = iter(nimg[40:,:,:].flatten())
    result = Counter(zip(z,z,z)).most_common(2)
    print result
    mcolor2 = np.array(result[1][0], dtype=np.float32)
    nimg2=np.zeros((h,w,c), dtype=np.uint8)
    print mcolor2
    for i in range(h):
        for j in range(w):
            #r=abs(nimg[i,j]-mcolor2).astype(dtype=np.uint8)            
            if tuple(nimg[i,j])==(0,0,0) or sim(mcolor2, nimg[i,j], 40): # or sim(mcolor3, nimg[i,j], 40):
                nimg2[i,j]=(0,0,0)
            else:
                nimg2[i,j]=(255,255,255)
    display_img_array(nimg2, width=600)
    nimg2 = cv2.cvtColor(nimg2, cv2.COLOR_BGR2GRAY)
    nimg3=np.zeros((h,w), dtype=np.uint8)
       
    for i in range(5,h-5):
        for j in range(5,w-5):
            r = nimg2[i-2:i+3, j-2:j+3].sum()
            if r <= 255*2:
                nimg3[i,j]=0
            elif  r >= 255*17:
                nimg3[i,j]=255
            else:
                nimg3[i,j]=nimg2[i,j]
    def remove_hline(img, i,j):
        if img[i-1,j]  >=127 or img[i+1,j]>=127:
            return
        if img[i, j-1]<127 and img[i, j+1]<127:
            img[i,j]=0
            return
        j1=j
        while j1>=0 and img[i,j1]>=127 and img[i-1,j1]  <127 and img[i+1,j1] <127:
            j1-=1
        j1+=1
        j2 = j
        while j2<img.shape[1] and  img[i,j2]>=127 and img[i-1,j2]  <127 and img[i+1,j2] <127:
            j2+=1
        if j2-j1 >=4:
            for j0 in range(j1,j2):
                img[i,j0]=0

    def remove_vline(img, i,j):
        if img[i,j-1]  >=127 or img[i,j+1]>=127:
            return
        if img[i-1, j]<127 and img[i+1, j]<127:
            img[i,j]=0
            return
        i1=i
        while i1>=0 and img[i1,j]>=127 and img[i1,j-1]  <127 and img[i1,j+1] <127:
            i1-=1
        i1+=1
        i2 = i
        while i2<img.shape[0] and  img[i2,j]>=127 and img[i2,j-1]  <127 and img[i2,j+1] <127:
            i2+=1
        if i2-i1 >=4:
            for i0 in range(i1,i2):
                img[i0,j]=0
    for i in range(2, h-2):
        for j in range(2,w-2):
            remove_hline(nimg3, i,j)
            remove_vline(nimg3, i,j)
    ximg3= img.copy() #cv2.cvtColor(nimg2, cv2.COLOR_GRAY2BGR)
    itv = None
    result =[]
    for j in range(2,w-2):
        if nimg3[:,j].max() ==0:
            cv2.polylines(ximg3, np.int32([[[j,0],[j,h]]]), False, (0,0,128))
            if itv:
                result.append(itv)
                itv = None
        else:
            if itv is None:
                itv=(j,j)
            else:
                itv = (itv[0], j)
    if itv is not None:
        result.append(itv)
    last = None
    result2=[]
    for itv in result:        
        if itv[1]-itv[0]>=16:
            if last and last[1]-last[0]>=9:
                result2.append(last)
            if itv[1]-itv[0]>=28:
                mid = int((itv[0]+itv[1])/2)
                result2.append( (itv[0],mid) )
                result2.append( (mid,itv[1]) )
            else:
                result2.append(itv)
            last = None
        elif last and last[1]+2 >= itv[0] and 30>itv[1]-last[0]>=10:
            result2.append((last[0], itv[1]))
            last = None
        elif itv[1]-itv[0]>=1:
            if last and last[1]-last[0] >=9:
                result2.append(last)                
            last = itv
        else:
            if last and last[1]-last[0] >=9:
                result2.append(last)     
            last = None   
    if last and last[1]-last[0] >=9:
        result2.append(last)   
    print result
    print result2
    for itv in result2:
        for i in range(h):
            if nimg3[i,itv[0]:itv[1]+1].max() ==0:
                cv2.polylines(ximg3, np.int32([[[itv[0],i],[itv[1]+1,i]]]), False, (0,0,128))
    
    display_img_array(ximg3, width=600)
    nimg4 = np.zeros_like(nimg3)
    for i in range(3, h-3):
        for j in range(3,w-3):
            s = nimg3[i-2:i+3, j-1:j+2].astype(int).sum()
            if s > 255*2:
                nimg4[i,j]=128
                if nimg3[i,j]:
                    nimg4[i,j]=255
    display_img_array(nimg4, None, width=600)
    #L = morphology.label(nimg4)
    L=skimage.measure.label(nimg4)
    print "Number of components:", np.max(L)
    print Counter(L.flatten()).most_common()
    contours, hierarchy = cv2.findContours(nimg4,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
    im = np.zeros_like(nimg4)
    cv2.drawContours(im,contours,-1,255,1)    
    display_img_array(im, None, width=600)
    
[((0, 0, 0), 3854), ((109, 121, 109), 8)]
[ 109.  121.  109.]
[(11, 22), (49, 50), (52, 62), (65, 65), (84, 85), (87, 88), (92, 107), (122, 135), (161, 173)]
[(11, 22), (49, 62), (92, 107), (122, 135), (161, 173)]
Number of components: 23
[(0, 11083), (4, 133), (12, 89), (9, 88), (13, 88), (14, 86), (11, 79), (1, 69), (3, 64), (2, 61), (15, 42), (16, 35), (17, 21), (5, 19), (7, 15), (6, 6), (19, 5), (20, 3), (21, 3), (22, 3), (23, 3), (8, 2), (18, 2), (10, 1)]
[((0, 0, 0), 3747), ((120, 129, 126), 16)]
[ 120.  129.  126.]
[(11, 22), (57, 57), (62, 77), (96, 110), (116, 116), (124, 139), (150, 150), (157, 159), (182, 194)]
[(11, 22), (62, 77), (96, 110), (124, 139), (182, 194)]
Number of components: 41
[(0, 11082), (23, 100), (21, 91), (22, 89), (13, 84), (2, 63), (6, 61), (15, 51), (20, 48), (12, 47), (5, 31), (3, 24), (16, 22), (25, 22), (31, 21), (24, 15), (10, 14), (29, 13), (1, 12), (7, 12), (27, 12), (14, 10), (26, 10), (9, 9), (32, 9), (30, 7), (17, 3), (18, 3), (19, 3), (33, 3), (34, 3), (35, 3), (36, 3), (37, 3), (39, 3), (40, 3), (41, 3), (4, 2), (11, 2), (38, 2), (8, 1), (28, 1)]
[((0, 0, 0), 3768), ((143, 118, 138), 5)]
[ 143.  118.  138.]
[(10, 21), (41, 56), (78, 90), (99, 100), (111, 125), (131, 133), (144, 158), (168, 181)]
[(10, 21), (41, 56), (78, 90), (111, 125), (144, 158), (168, 181)]
Number of components: 37
[(0, 10912), (18, 108), (9, 105), (6, 102), (7, 100), (4, 94), (26, 74), (3, 69), (5, 68), (29, 58), (2, 31), (10, 29), (23, 29), (14, 24), (1, 21), (13, 20), (16, 19), (20, 18), (24, 18), (27, 16), (32, 16), (11, 14), (8, 8), (21, 8), (28, 6), (19, 5), (17, 4), (34, 4), (12, 3), (15, 3), (22, 2), (25, 2), (30, 2), (33, 2), (35, 2), (37, 2), (31, 1), (36, 1)]
[((0, 0, 0), 3707), ((96, 124, 111), 11)]
[  96.  124.  111.]
[(13, 31), (39, 41), (46, 46), (48, 63), (74, 86), (94, 97), (103, 120), (124, 127), (129, 143), (167, 177)]
[(13, 31), (48, 63), (74, 86), (103, 120), (124, 143), (167, 177)]
Number of components: 43
[(0, 10881), (21, 113), (5, 96), (36, 95), (28, 84), (19, 76), (4, 71), (20, 70), (13, 66), (24, 66), (1, 65), (18, 54), (12, 30), (35, 25), (31, 24), (10, 23), (2, 20), (32, 14), (7, 13), (33, 12), (8, 11), (17, 10), (38, 9), (27, 8), (30, 8), (34, 8), (39, 7), (25, 6), (22, 4), (3, 3), (14, 3), (15, 3), (16, 3), (6, 2), (9, 2), (11, 2), (29, 2), (37, 2), (40, 2), (41, 2), (43, 2), (23, 1), (26, 1), (42, 1)]
[((0, 0, 0), 3651), ((105, 139, 98), 9)]
[ 105.  139.   98.]
[(29, 42), (44, 61), (69, 69), (95, 109), (131, 136), (138, 143), (148, 150), (163, 180), (184, 185)]
[(29, 42), (44, 61), (95, 109), (131, 143), (163, 180)]
Number of components: 34
[(0, 11100), (9, 110), (7, 107), (3, 95), (21, 85), (23, 80), (1, 77), (6, 60), (8, 39), (14, 30), (24, 24), (26, 20), (29, 20), (19, 19), (27, 19), (28, 19), (11, 18), (20, 18), (22, 6), (2, 5), (4, 5), (5, 5), (30, 5), (10, 4), (34, 4), (15, 3), (16, 3), (17, 3), (18, 3), (31, 3), (32, 3), (33, 3), (13, 2), (25, 2), (12, 1)]
[((0, 0, 0), 3774), ((107, 127, 104), 12)]
[ 107.  127.  104.]
[(14, 29), (65, 79), (87, 101), (103, 104), (134, 152), (167, 167), (172, 173), (175, 191)]
[(14, 29), (65, 79), (87, 104), (134, 152), (175, 191)]
Number of components: 29
[(0, 11088), (7, 94), (3, 81), (5, 77), (19, 74), (11, 72), (8, 71), (4, 70), (1, 65), (18, 41), (2, 40), (22, 38), (9, 28), (24, 24), (25, 21), (10, 19), (21, 18), (27, 18), (6, 15), (28, 9), (15, 8), (26, 5), (29, 4), (12, 3), (13, 3), (14, 3), (16, 3), (20, 3), (23, 3), (17, 2)]
[((0, 0, 0), 3425), ((243, 250, 255), 24)]
[ 243.  250.  255.]
[(6, 26), (31, 31), (40, 41), (46, 60), (75, 86), (107, 117), (134, 135), (145, 163), (165, 168), (177, 192)]
[(6, 26), (46, 60), (75, 86), (107, 117), (145, 163), (177, 192)]
Number of components: 50
[(0, 10662), (2, 126), (22, 126), (15, 120), (14, 114), (1, 104), (16, 88), (4, 83), (13, 81), (17, 69), (19, 60), (3, 56), (20, 47), (10, 25), (21, 23), (11, 22), (9, 21), (33, 14), (35, 14), (30, 11), (39, 11), (46, 10), (32, 8), (37, 8), (27, 6), (31, 6), (50, 6), (6, 5), (8, 5), (26, 5), (29, 5), (34, 5), (38, 5), (7, 4), (18, 4), (5, 3), (23, 3), (24, 3), (25, 3), (36, 3), (40, 3), (41, 3), (42, 3), (47, 3), (48, 3), (49, 3), (12, 2), (43, 2), (45, 2), (28, 1), (44, 1)]
[((0, 0, 0), 3743), ((124, 129, 97), 10)]
[ 124.  129.   97.]
[(18, 29), (31, 34), (42, 53), (63, 78), (103, 120), (128, 143), (173, 186)]
[(18, 34), (42, 53), (63, 78), (103, 120), (128, 143), (173, 186)]
Number of components: 32
[(0, 11047), (18, 99), (6, 94), (12, 84), (5, 78), (11, 66), (2, 63), (17, 52), (9, 51), (23, 47), (15, 38), (25, 35), (16, 34), (1, 30), (7, 30), (13, 27), (3, 26), (4, 24), (8, 15), (24, 11), (26, 10), (14, 8), (10, 4), (19, 3), (20, 3), (21, 3), (28, 3), (29, 3), (30, 3), (31, 3), (32, 3), (27, 2), (22, 1)]
[((0, 0, 0), 3801), ((140, 121, 118), 11)]
[ 140.  121.  118.]
[(8, 20), (22, 22), (34, 35), (54, 66), (90, 105), (137, 151), (154, 170)]
[(8, 22), (54, 66), (90, 105), (137, 151), (154, 170)]
Number of components: 26
[(0, 11211), (4, 105), (5, 74), (19, 71), (11, 69), (18, 67), (9, 64), (1, 62), (25, 52), (24, 40), (16, 30), (10, 29), (15, 21), (8, 19), (13, 18), (2, 17), (20, 14), (17, 11), (14, 4), (6, 3), (7, 3), (21, 3), (22, 3), (23, 3), (26, 3), (3, 2), (12, 2)]
[((0, 0, 0), 3733), ((108, 123, 115), 6)]
[ 108.  123.  115.]
[(5, 5), (23, 36), (62, 72), (84, 100), (123, 136), (178, 192)]
[(23, 36), (62, 72), (84, 100), (123, 136), (178, 192)]
Number of components: 26
[(0, 11148), (17, 125), (1, 91), (5, 80), (14, 80), (2, 79), (9, 76), (3, 50), (6, 50), (10, 24), (12, 24), (26, 23), (16, 21), (7, 19), (19, 18), (24, 18), (4, 16), (8, 14), (15, 11), (18, 9), (22, 8), (11, 5), (23, 5), (13, 2), (21, 2), (20, 1), (25, 1)]
[((0, 0, 0), 3804), ((128, 136, 105), 5)]
[ 128.  136.  105.]
[(7, 8), (13, 28), (64, 79), (82, 83), (101, 111), (121, 121), (123, 123), (129, 142), (144, 147), (174, 192)]
[(13, 28), (64, 79), (101, 111), (129, 147), (174, 192)]
Number of components: 38
[(0, 11061), (5, 114), (18, 112), (1, 96), (3, 86), (14, 74), (4, 62), (19, 46), (21, 39), (16, 38), (22, 35), (9, 34), (20, 29), (17, 25), (33, 24), (12, 18), (30, 18), (6, 15), (36, 12), (23, 10), (15, 5), (24, 5), (25, 4), (2, 3), (8, 3), (10, 3), (11, 3), (27, 3), (28, 3), (35, 3), (37, 3), (38, 3), (7, 2), (13, 2), (32, 2), (34, 2), (26, 1), (29, 1), (31, 1)]
[((0, 0, 0), 3787), ((128, 113, 97), 12)]
[ 128.  113.   97.]
[(9, 20), (38, 55), (77, 78), (80, 97), (101, 117), (133, 134), (174, 183)]
[(9, 20), (38, 55), (80, 97), (101, 117), (174, 183)]
Number of components: 27
[(0, 11184), (17, 125), (2, 73), (1, 67), (18, 64), (9, 62), (22, 62), (10, 61), (7, 53), (21, 44), (11, 31), (15, 26), (8, 19), (14, 19), (25, 19), (19, 17), (6, 16), (24, 15), (12, 11), (27, 11), (16, 4), (3, 3), (4, 3), (23, 3), (5, 2), (13, 2), (20, 2), (26, 2)]
[((0, 0, 0), 3777), ((144, 96, 138), 9)]
[ 144.   96.  138.]
[(6, 20), (38, 53), (83, 104), (106, 115), (117, 118), (137, 153), (169, 185)]
[(6, 20), (38, 53), (83, 104), (106, 118), (137, 153), (169, 185)]
Number of components: 48
[(0, 10899), (9, 121), (33, 106), (10, 98), (23, 95), (40, 90), (29, 71), (7, 59), (5, 53), (1, 49), (11, 46), (15, 33), (22, 30), (24, 22), (14, 21), (25, 21), (37, 21), (42, 20), (39, 15), (43, 15), (38, 14), (45, 13), (44, 11), (30, 9), (21, 8), (2, 6), (32, 4), (6, 3), (8, 3), (12, 3), (16, 3), (17, 3), (18, 3), (19, 3), (20, 3), (26, 3), (3, 2), (4, 2), (13, 2), (28, 2), (31, 2), (35, 2), (36, 2), (41, 2), (46, 2), (48, 2), (27, 1), (34, 1), (47, 1)]
[((0, 0, 0), 3758), ((103, 123, 118), 12)]
[ 103.  123.  118.]
[(6, 21), (42, 57), (77, 78), (82, 94), (110, 122), (125, 125), (137, 154), (173, 187)]
[(6, 21), (42, 57), (82, 94), (110, 122), (137, 154), (173, 187)]
Number of components: 32
[(0, 10871), (23, 121), (2, 92), (8, 92), (22, 91), (4, 87), (18, 87), (16, 71), (1, 61), (11, 61), (24, 60), (3, 35), (12, 28), (19, 27), (14, 25), (17, 22), (21, 22), (28, 22), (5, 21), (6, 18), (27, 18), (15, 14), (20, 12), (9, 11), (25, 5), (29, 5), (26, 4), (7, 3), (10, 3), (30, 3), (31, 3), (32, 3), (13, 2)]
[((0, 0, 0), 3778), ((109, 139, 128), 9)]
[ 109.  139.  128.]
[(12, 13), (17, 30), (36, 50), (68, 80), (87, 87), (108, 124), (136, 153), (172, 174), (176, 187)]
[(17, 30), (36, 50), (68, 80), (108, 124), (136, 153), (172, 187)]
Number of components: 38
[(0, 11015), (16, 117), (15, 88), (12, 87), (10, 86), (5, 76), (21, 74), (13, 62), (7, 37), (9, 36), (4, 33), (8, 31), (19, 28), (30, 25), (34, 24), (6, 23), (20, 18), (11, 17), (14, 15), (17, 15), (18, 13), (24, 13), (29, 12), (25, 10), (32, 10), (27, 7), (33, 5), (1, 3), (2, 3), (3, 3), (26, 3), (35, 2), (36, 2), (38, 2), (22, 1), (23, 1), (28, 1), (31, 1), (37, 1)]
[((0, 0, 0), 3722), ((113, 128, 101), 8)]
[ 113.  128.  101.]
[(17, 31), (51, 63), (69, 70), (75, 75), (77, 79), (82, 83), (89, 89), (92, 105), (145, 157), (174, 186)]
[(17, 31), (51, 63), (92, 105), (145, 157), (174, 186)]
Number of components: 33
[(0, 10998), (7, 109), (2, 104), (14, 101), (3, 99), (6, 99), (8, 80), (15, 76), (11, 57), (1, 54), (17, 36), (16, 34), (22, 30), (18, 26), (20, 21), (19, 11), (23, 9), (12, 5), (28, 5), (24, 4), (25, 4), (26, 4), (29, 4), (4, 3), (5, 3), (9, 3), (10, 3), (27, 3), (31, 3), (32, 3), (33, 3), (13, 2), (21, 2), (30, 2)]
[((0, 0, 0), 3773), ((99, 126, 100), 17)]
[  99.  126.  100.]
[(5, 19), (40, 53), (76, 87), (97, 113), (136, 153), (171, 184)]
[(5, 19), (40, 53), (76, 87), (97, 113), (136, 153), (171, 184)]
Number of components: 24
[(0, 10873), (5, 108), (14, 102), (4, 101), (8, 95), (10, 85), (3, 76), (11, 65), (9, 64), (21, 60), (2, 51), (1, 46), (24, 42), (7, 41), (20, 28), (17, 27), (16, 26), (22, 22), (15, 18), (6, 16), (12, 15), (23, 15), (18, 13), (13, 10), (19, 1)]
[((0, 0, 0), 3746), ((84, 111, 121), 18)]
[  84.  111.  121.]
[(11, 13), (17, 33), (35, 35), (61, 62), (64, 73), (103, 109), (111, 131), (154, 154), (168, 169), (180, 194)]
[(17, 33), (61, 73), (111, 131), (180, 194)]
Number of components: 39
[(0, 10992), (22, 128), (21, 105), (29, 95), (9, 78), (17, 76), (7, 75), (5, 71), (19, 66), (31, 46), (8, 27), (6, 24), (33, 22), (24, 20), (25, 20), (20, 19), (34, 17), (32, 13), (23, 12), (4, 11), (11, 11), (28, 9), (18, 6), (26, 6), (10, 5), (15, 5), (30, 4), (36, 4), (2, 3), (3, 3), (12, 3), (13, 3), (14, 3), (16, 3), (35, 3), (37, 3), (38, 3), (1, 2), (27, 2), (39, 2)]
[((0, 0, 0), 3707), ((103, 130, 121), 9)]
[ 103.  130.  121.]
[(17, 38), (40, 40), (48, 50), (58, 76), (99, 102), (104, 119), (134, 151), (153, 153), (172, 188)]
[(17, 38), (58, 76), (99, 119), (134, 151), (172, 188)]
Number of components: 38
[(0, 10997), (13, 110), (18, 106), (2, 89), (7, 81), (6, 58), (12, 49), (11, 46), (15, 44), (19, 42), (21, 42), (8, 39), (17, 32), (9, 26), (5, 23), (28, 23), (30, 19), (4, 16), (10, 15), (23, 14), (1, 13), (24, 13), (3, 12), (16, 12), (14, 11), (26, 10), (27, 9), (35, 9), (22, 8), (20, 6), (25, 4), (29, 4), (32, 4), (36, 4), (37, 3), (31, 2), (34, 2), (38, 2), (33, 1)]
[((0, 0, 0), 3812), ((120, 104, 122), 8)]
[ 120.  104.  122.]
[(9, 26), (34, 34), (48, 61), (80, 110), (131, 145), (150, 151), (161, 161), (163, 163), (167, 171), (176, 191), (193, 194)]
[(9, 26), (48, 61), (80, 95), (95, 110), (131, 145), (176, 194)]
Number of components: 41
[(0, 10979), (7, 101), (1, 91), (20, 91), (12, 84), (11, 73), (30, 64), (21, 58), (18, 56), (29, 47), (10, 45), (22, 39), (13, 35), (9, 32), (28, 28), (16, 21), (3, 15), (19, 15), (32, 12), (23, 11), (31, 11), (24, 10), (34, 9), (25, 8), (27, 7), (38, 6), (6, 5), (33, 5), (39, 5), (8, 4), (35, 4), (37, 4), (40, 4), (2, 3), (4, 3), (5, 3), (26, 3), (14, 2), (17, 2), (36, 2), (41, 2), (15, 1)]
In [4]:
def sim(c1, c2, D=80):
    return sum(abs(int(c1[k])-int(c2[k])) for k in range(3))<=D
imgs = [cv2.imread('img/rail{}.jpg'.format(i)) for i in range(10)]
for img in imgs:
    display_img_array(img,  width=800)
    z = iter(img.flatten())
    mcolor = np.array(Counter(zip(z,z,z)).most_common(1)[0][0], dtype=np.float32)
    h,w,c = img.shape
    nimg=np.zeros((h,w,c), dtype=np.uint8)
    for i in range(h-5):
        for j in range(w-5):
            if sim(mcolor, img[i,j],65):
                nimg[i,j]=(0,0,0)
            else:
                nimg[i,j]=(255,255,255)
    #display_img_array(nimg)
    img = nimg
    nimg=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    def remove_hline(img, i,j):
        if img[i-1,j]  >=127 or img[i+1,j]>=127:
            return
        if img[i, j-1]<127 and img[i, j+1]<127:
            img[i,j]=0
            return
        j1=j
        while j1>=0 and img[i,j1]>=127 and img[i-1,j1]  <127 and img[i+1,j1] <127:
            j1-=1
        j1+=1
        j2 = j
        while j2<img.shape[1] and  img[i,j2]>=127 and img[i-1,j2]  <127 and img[i+1,j2] <127:
            j2+=1
        if j2-j1 >=4:
            for j0 in range(j1,j2):
                img[i,j0]=0

    def remove_vline(img, i,j):
        if img[i,j-1]  >=127 or img[i,j+1]>=127:
            return
        if img[i-1, j]<127 and img[i+1, j]<127:
            img[i,j]=0
            return
        i1=i
        while i1>=0 and img[i1,j]>=127 and img[i1,j-1]  <127 and img[i1,j+1] <127:
            i1-=1
        i1+=1
        i2 = i
        while i2<img.shape[0] and  img[i2,j]>=127 and img[i2,j-1]  <127 and img[i2,j+1] <127:
            i2+=1
        if i2-i1 >=4:
            for i0 in range(i1,i2):
                img[i0,j]=0
                
    for i in range(2,h-2):
        for j in range(2,w-2):
            if nimg[i,j]==0:
                continue
            remove_hline(nimg, i,j)          
            remove_vline(nimg,i,j)
    display_img_array(nimg, None, width=800)