Home > front end >  How to compute Mean and Standard Deviation of Edges (Canny Edge Detection in OpenCV)
How to compute Mean and Standard Deviation of Edges (Canny Edge Detection in OpenCV)

Time:11-17

I have images where you can see the halftone of the print and I want to calculate the mean and standard deviation of the dots. I'm using OpenCV and Canny Edge Detection to isolate the dots like this

import cv2

img = cv2.imread('img/color_dots.png')
img_blur = cv2.GaussianBlur(img, (3,3), 0)

edges = cv2.Canny(image=img_blur, threshold1=50, threshold2=100)

This is the original image:

enter image description here

And here the canny edged image:

enter image description here

I think not all dots got recognized, especially the yellow one... And I am not sure if my approach is correct with Edge Detection or better find contours? Anyway how can I compute the average sizes of these dots?

CodePudding user response:

Here is one way to do that in Python/OpenCV.

Threshold the background to isolate the dots. Then you can compute the mean of the colors directly in OpenCV using a mask. Then the standard deviation can be obtained from the square root of the variance, which is the mean of the square of the image minus the square of the mean of the image. See enter image description here

import cv2
import numpy as np

img = cv2.imread("color_dots.png")

# threshold on background color
lower = (215,215,215)
upper = (255,255,255)
thresh = cv2.inRange(img, lower, upper)

# invert so dots are white
thresh = 255 - thresh
#thresh = cv2.cvtColor(thresh, cv2.COLOR_GRAY2BGR)

# get mean colors of dots using mask
mean_values = cv2.mean(img, mask=thresh)[0:3]
mean_values = list(mean_values)
print("mean:", mean_values)

# compute square of image (as floats) and compute mean of squared image
imgf = img.astype(np.float64)
imgf2 = imgf * imgf
mean2_values = cv2.mean(imgf2, mask=thresh)[0:3]

# convert mean of image and mean of image squared tuples to arrays
mean_values_arr = np.array([mean_values])
mean2_values_arr = np.array([mean2_values])

# compute the variance from the mean of image and mean of image squared arrays
variance_values_arr = mean2_values_arr - (mean_values_arr)*(mean_values_arr)

# compute sqrt to form std
std_values_arr = np.sqrt(variance_values_arr)

# convert array to simple list
std_values = list(std_values_arr[0])
print("std:", std_values)

# save result
cv2.imwrite("color_dots_threshold.png",thresh)

cv2.imshow("thresh", thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()

Thresholded Image:

enter image description here

Mean and Standard Deviation:

mean: [226.75895493644884, 209.73003594813198, 212.56531647194763]
std: [21.657486571574186, 19.53005158116894, 30.588081007741454]

ADDITION

Here is an alternate more direct way using Numpy.

import cv2
import numpy as np

img = cv2.imread("color_dots.png")

# threshold on background color
lower = (215,215,215)
upper = (255,255,255)
thresh = cv2.inRange(img, lower, upper)

# invert so dots are white
thresh = 255 - thresh

# separate channels 
b,g,r = cv2.split(img)

# compute mean of each channel
bmean = np.mean(b[np.where(thresh==255)])
gmean = np.mean(g[np.where(thresh==255)])
rmean = np.mean(r[np.where(thresh==255)])

# compute std of each channel
bstd = np.std(b[np.where(thresh==255)])
gstd = np.std(g[np.where(thresh==255)])
rstd = np.std(r[np.where(thresh==255)])

# print results
print("mean:", bmean,gmean,rmean)
print("std:", bstd,gstd,rstd)

# save result
cv2.imwrite("color_dots_threshold.png",thresh)

cv2.imshow("thresh", thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()

Mean and Standard Deviation:

mean: 226.75895493644884 209.73003594813198 212.56531647194763
std: 21.657486571574225 19.53005158116893 30.58808100774145

ADDITION 2

Here is probably the simplest way using OpenCV.

import cv2
import numpy as np

img = cv2.imread("color_dots.png")

# threshold on background color
lower = (215,215,215)
upper = (255,255,255)
thresh = cv2.inRange(img, lower, upper)

# invert so dots are white
thresh = 255 - thresh

# compute mean and standard deviation
mean, std = cv2.meanStd(img, mask=thresh)[0:3]

# print results
print("mean:", mean)
print("std:", std)

# save result
cv2.imwrite("color_dots_threshold.png",thresh)

cv2.imshow("thresh", thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()

Mean and Standard Deviation:

mean: 226.75895493644884 209.73003594813198 212.56531647194763
std: 21.657486571574225 19.53005158116893 30.58808100774145
  • Related