1

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:

enter image description here

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")
Vasilis G.
  • 7,556
  • 4
  • 19
  • 29
freddykrueger
  • 309
  • 4
  • 17
  • Watch [here](https://stackoverflow.com/questions/48303309/use-cv2-connectedcomponents-and-eliminate-elements-with-a-small-number-of-pixels)! Another algorithm, but perfect result! – freddykrueger Jan 18 '18 at 13:09

0 Answers0