I have an iOS app that does image processing. The images are black background with a single solid white body that is a complicated shape. I can use openCV or CIEdges filter to get an image of the edge as shown below. But the thickness of that edge is variable and unknown. Is there any way that I can make the edge of a specified thickness? For example 3 pixels thick?
-
yes, discard this approach. don't fix accidents, prevent them. -- instead extract contours from the original picture (thresholded if needed). *don't* calculate a picture like the one you showed. if you have to, at least let's talk about _how_ you do that... which you haven't said. -- perhaps you should present more context (i.e. pictures _before_ you've processed them, and from all steps in between) – Christoph Rackwitz Jan 29 '22 at 23:30
-
yep. that was my intent. all i did here was apply a ciedges filter to see how it came out. but i want to do something that will give me a uniform thickness. so if you know how to do that, it would be great. I'll add more pictures when I am back at my desk. – Bob Jan 30 '22 at 12:44
-
What do you call "make the edge of a specified thickness exactly" ? Does it need to be antialiased ? – Jan 31 '22 at 10:21
-
I guess that this could be easier to do from the original image, if we can see it... – Jan 31 '22 at 10:21
-
Next question: WHY would you want that ? – Jan 31 '22 at 10:29
1 Answers
You can calculate the skeleton of the image. The skeleton is a transformation used to thin a binary region such that its extent and connectivity is preserved. In this case, it will yield edges of one pixel of thickness. The skeletonize/thinning function is part of OpenCV's extended image processing module, in Python (you do not mention what implementation of OpenCV you are using):
# Imports:
import cv2
import numpy as np
# image path
path = "D://opencvImages//"
fileName = "contour.png"
# Reading an image in default mode:
inputImage = cv2.imread(path + fileName)
# Convert to grayscale:
grayscaleImage = cv2.cvtColor(inputImage, cv2.COLOR_BGR2GRAY)
# Compute the skeleton:
skeleton = cv2.ximgproc.thinning(grayscaleImage, None, 1)
cv2.imshow("Skeleton", skeleton)
cv2.waitKey(0)
This gif
compares your original image and its skeleton, where you can see the thickness reduction. The image has been resized, so you see a little bit of alias and the post-processed edges look non-constant, but the skeleton always normalizes the thickness of a curve to one pixel (hint: open the gif
in a new tab to see the full-sized animation):

If you want edges of a specific thickness, you can dilate
the skeleton a couple of times. In C++, you should #include <opencv2/ximgproc.hpp>
to use the extended image processing module, and the function prototype is cv::ximgproc::thinning(InputArray src, OutputArray dst, int thinningType=THINNING_ZHANGSUEN)
. More info here.

- 5,227
- 4
- 13
- 29