I use the CCL algorithm of Spencer Whitt from Github to remove detected road markings from Noise.
First, I run the CCL algorithm over an image so that it recognizes contiguous elements. Now I extended the algorithm so that it ignores elements with a small number of pixels. So I tried to sort and filter the dictionary created by the CCL algorithm. In the additional code, therefore, keys that are not enough are deleted with the corresponding values.
Unfortunately, the additional code not only deletes small elements, but also fragments up the "large" contiguous road markings. Why?
Image:
CCL algorithm:
from PIL import Image
import PIL
from PIL import ImageOps
import collections
import operator
import numpy as np
import sys
import math, random
from itertools import product
from ufarray import *
Image.MAX_IMAGE_PIXELS = 1000000000
import cv2
def run(img):
data = img.load()
width, height = img.size
# Union find data structure
uf = UFarray()
#
# First pass
#
# Dictionary of point:label pairs
labels = {}
for y, x in product(range(height), range(width)):
#
# Pixel names were chosen as shown:
#
# -------------
# | a | b | c |
# -------------
# | d | e | |
# -------------
# | | | |
# -------------
#
# The current pixel is e
# a, b, c, and d are its neighbors of interest
#
# 255 is white, 0 is black
# White pixels part of the background, so they are ignored
# If a pixel lies outside the bounds of the image, it default to white
#
# If the current pixel is white, it's obviously not a component...
if data[x, y] == 255:
pass
# If pixel b is in the image and black:
# a, d, and c are its neighbors, so they are all part of the same component
# Therefore, there is no reason to check their labels
# so simply assign b's label to e
elif y > 0 and data[x, y-1] == 0:
labels[x, y] = labels[(x, y-1)]
# If pixel c is in the image and black:
# b is its neighbor, but a and d are not
# Therefore, we must check a and d's labels
elif x+1 < width and y > 0 and data[x+1, y-1] == 0:
c = labels[(x+1, y-1)]
labels[x, y] = c
# If pixel a is in the image and black:
# Then a and c are connected through e
# Therefore, we must union their sets
if x > 0 and data[x-1, y-1] == 0:
a = labels[(x-1, y-1)]
uf.union(c, a)
# If pixel d is in the image and black:
# Then d and c are connected through e
# Therefore we must union their sets
elif x > 0 and data[x-1, y] == 0:
d = labels[(x-1, y)]
uf.union(c, d)
# If pixel a is in the image and black:
# We already know b and c are white
# d is a's neighbor, so they already have the same label
# So simply assign a's label to e
elif x > 0 and y > 0 and data[x-1, y-1] == 0:
labels[x, y] = labels[(x-1, y-1)]
# If pixel d is in the image and black
# We already know a, b, and c are white
# so simpy assign d's label to e
elif x > 0 and data[x-1, y] == 0:
labels[x, y] = labels[(x-1, y)]
# All the neighboring pixels are white,
# Therefore the current pixel is a new component
else:
labels[x, y] = uf.makeLabel()
#
# Second pass
#
uf.flatten()
colors = {}
# Image to display the components in a nice, colorful way
output_img = Image.new("RGB", (width, height))
outdata = output_img.load()
for (x, y) in labels:
# Name of the component the current point belongs to
component = uf.find(labels[(x, y)])
# Update the labels with correct information
labels[(x, y)] = component
# Associate a random color with this component
if component not in colors:
colors[component] = (random.randint(0,255), random.randint(0,255),random.randint(0,255))
# Colorize the image
outdata[x, y] = colors[component]
return (labels, output_img)
Additional code:
def main():
# Open the image
img = Image.open("files/motorway/gabor/motorway_gabor_S.tiff")
img = PIL.ImageOps.invert(img)
# Threshold the image, this implementation is designed to process b+w
# images only
img = img.point(lambda p: p > 190 and 255)
img = img.convert('1')
# labels is a dictionary of the connected component data in the form:
# (x_coordinate, y_coordinate) : component_id
#
# if you plan on processing the component data, this is probably what you
# will want to use
#
# output_image is just a frivolous way to visualize the components.
(labels, output_img) = run(img)
# output_img.show()
output_img.save("files/motorway/gabor/motorway_gabor_S_cc1.tiff")
################################################################################
sorted_x = sorted(labels.items(), key=operator.itemgetter(1))
str_labels = str(sorted_x) # Convert Dictionary to String, remove unnecessary characters
str_labels = str_labels.replace("{", "[")
str_labels = str_labels.replace("}", "]")
str_labels = str_labels.replace("(", "")
str_labels = str_labels.replace(")", "")
str_labels = str_labels.replace(":", ",")
# print str_labels[:100]
int_labels = eval(str_labels) # Transforming back into an integer list
i = 0
key = []
value = []
#int_labels2 = list(int_labels)
while i < len(int_labels)/3:
key.append(int_labels[3*i]) # x (keys)
key.append(int_labels[3 * i + 1]) # y (keys)
value.append(int_labels[3 * i + 2]) # values
i = i + 1
counter = collections.Counter(value) # Counting the frequency of "values"
counter_values = counter.values()
################################################################################
# Selection
# Sorting out "keys" and "values" that are too big/small
# key2 = relevant "keys"
# value2 = to key2 appropriate relevant values
i = 0
k = 0
v = 0
key2 = []
key3 = []
value2 = []
value3 = []
help = []
while i < len(counter_values):
if counter_values[i] >= 80:# and counter_values[i] <= 71:
value2.append(counter_values[v]*2)
v = v + 1
while k < counter_values[i]*2 + sum(help)*2:
key2.append(key[k])
k = k + 1
else:
value3.append(counter_values[v]*2)
v = v + 1
while k < counter_values[i]*2 + sum(help)*2:
key3.append(key[k])
k = k + 1
help.append(counter_values[i])
i = i + 1
#####################################################################
# Image to display the components in a nice, colorful way
width, height = img.size
output_img = Image.new("RGB", (width, height))
outdata = output_img.load()
# list (key2) to x- and y-tuple-pairs
i = 0
key2t = []
while i < len(key2):
key2t.append(tuple(key2[i:i + 2]))
i = i + 2
# transform value2-list
i = 0
j = 0
k = 0
value2_full = []
while i < len(value2):
while j < value2[i]:
value2_full.append(k)
j = j + 1
j = 0
i = i + 1
k = k + 1
d = dict(zip(key2t, value2_full))
colors = {}
i = 0
for (x, y) in d:
if value2_full[i] not in colors:
colors[value2_full[i]] = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
# Colorize the image
outdata[x, y] = colors[value2_full[i]]
output_img.save("files/motorway/gabor/motorway_gabor_S_cc2.tiff")