Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thicken a one pixel line

I'm using OpenCV to do some image processing on Python. I'm trying to overlay an outline on an image where the outline was made from a mask. I'm using cv2.Canny() to get the outline of the mask, then changing that to a color using cv2.cvtColor() then finally converting that edge to cyan using outline[np.where((outline == [255,255,255]).all(axis=2))] = [180,105,255]. My issue now is that this is a one pixel thick line and can barely be seen on large images. This outline is all [0,0,0] except on the points I apply as a mask onto my color image using cv2.bitwise_or(img, outline.

I'm currently thickening this outline by brute forcing and checking every single pixel in the bitmap to check if any of its neighbors are [180,105,255] and if so, that pixel will also change. This is very slow. Is there any way using numpy or openCV to do this automatically? I was hoping for some conditional indexing with numpy, but can't find anything.

like image 688
TheStrangeQuark Avatar asked Oct 23 '17 18:10

TheStrangeQuark


Video Answer


1 Answers

Here are two methods depending on the situation:

  • cv2.dilate() - enhance all white pixels
  • cv2.drawContours() - enhance specific pixels

Example

Using this input image

enter image description here

import cv2
import numpy as np

# Create test image
mask = np.zeros((200,200,3), dtype=np.uint8)
cv2.line(mask, (50, 100), (150, 100), (255,255,255), 1)

Method #1

All pixels in the foreground (white) will have its area increased with cv2.dilate(). We create a structuring element and dilate. More iterations will generate a thicker line

iterations=1 (left), iterations=2 (middle), iterations=3 (right)

enter image description here enter image description here enter image description here

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
dilate = cv2.dilate(mask, kernel, iterations=1)

Method #2

When we want to only enhance a particular part of an image but leave other sections untouched, we can use cv2.drawContours(). We can specify the color and adjust the size using the thickness parameter. The result will be similar to cv2.dilate() with the added benefit of color selection

enter image description here

gray = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
cnts = cv2.findContours(gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

for c in cnts:
    cv2.drawContours(mask, [c], -1, (255,255,255), thickness=15)
like image 187
nathancy Avatar answered Sep 17 '22 14:09

nathancy