python - 非零值的 opencv meanStdDev
问题描述
我想计算忽略零的图像的平均值和统计数据。由于我没有弄清楚如何在 cv2.meanStdDev 中为此使用 mask 参数,我认为我可以通过一些数学来解决问题。
根据https://github.com/opencv/opencv/blob/master/3rdparty/carotene/src/meanstddev.cpp
标准偏差根据https://en.wikipedia.org/wiki/Standard_deviation计算为:
f64 stddev = sqrt(std::max(fsqsum * itotal - mean * mean, 0.0));
下面的代码现在尝试“重新使用该公式”来修复为所有不应考虑的零添加的值的结果
import cv2
import numpy as np
import math
def test_Stats():
h=2
w=2
channels=3
image=np.zeros((h,w,channels), np.uint8)
image[0,0]=(100,50,200)
image[0,1]=(120,60,220)
(means, stds) = cv2.meanStdDev(image)
gmean,bmean,rmean=means.flatten()
gstds,bstds,rstds=stds.flatten()
print ("means %.1f %.1f %.1f " % (gmean,bmean,rmean))
print ("stds %.1f %.1f %.1f " % (gstds,bstds,rstds))
b = image[:,:,0]
g = image[:,:,1]
r = image[:,:,2]
h, w = image.shape[:2]
pixels=h*w
nonzerotupel= cv2.countNonZero(b),cv2.countNonZero(g),cv2.countNonZero(r)
nonzero=max(nonzerotupel)
print ("%d pixel %d non-zero" % (pixels,nonzero))
factor=pixels/nonzero
fgmean=gmean*factor
fbmean=bmean*factor
frmean=rmean*factor
print ("non-zero means %.1f %.1f %.1f" % (fgmean,fbmean,frmean))
fsqsumb=(bstds*bstds+bmean*bmean)/pixels
fsqsumg=(gstds*gstds+gmean*gmean)/pixels
fsqsumr=(rstds*rstds+rmean*rmean)/pixels
fstdsb=math.sqrt(max(fsqsumb*nonzero-fbmean*fbmean,0))
fstdsg=math.sqrt(max(fsqsumg*nonzero-fgmean*fgmean,0))
fstdsr=math.sqrt(max(fsqsumr*nonzero-frmean*frmean,0))
print ("non-zero stds %.1f %.1f %.1f" % (fstdsb,fstdsg,fstdsr))
运行它:
test_Stats()
给出:
means 55.0 27.5 105.0
stds 55.5 27.7 105.2
4 pixel 2 non-zero
non-zero means 110.0 55.0 210.0
non-zero stds 0.0 0.0 0.0
所以看起来我犯了一些错误。在此示例中,非零标准的预期结果将是 10.0,5.0,10.0
解决办法是什么?
修复后如何进一步改进此代码?
解决方案
我想我发现了错误。第一个问题的答案:解决办法是什么?在下面。
原因:c++ 版本中的 itotal 意思是“逆总数” - 1/total。我以为它的意思是“整数总数”。因此需要修复像素非零调整。结果是现在
means 55.00 27.50 105.00
stds 55.45 27.73 105.24
4 pixel 2 non-zero
non-zero means 110.00 55.00 210.00
fsqsum 6100.00 24400.00 88400.00
non-zero stds 5.00 10.00 10.00
看起来不错 问题 2:修复后如何进一步改进此代码? 仍然开放
def test_Stats():
h=2
w=2
channels=3
image=np.zeros((h,w,channels), np.uint8)
image[0,0]=(100,50,200)
image[0,1]=(120,60,220)
(means, stds) = cv2.meanStdDev(image)
gmean,bmean,rmean=means.flatten()
gstds,bstds,rstds=stds.flatten()
print ("means %.2f %.2f %.2f " % (gmean,bmean,rmean))
print ("stds %.2f %.2f %.2f " % (gstds,bstds,rstds))
b = image[:,:,0]
g = image[:,:,1]
r = image[:,:,2]
h, w = image.shape[:2]
pixels=h*w
nonzerotupel= cv2.countNonZero(b),cv2.countNonZero(g),cv2.countNonZero(r)
nonzero=max(nonzerotupel)
print ("%d pixel %d non-zero" % (pixels,nonzero))
factor=pixels/nonzero
fgmean=gmean*factor
fbmean=bmean*factor
frmean=rmean*factor
print ("non-zero means %.2f %.2f %.2f" % (fgmean,fbmean,frmean))
fsqsumb=(bstds*bstds+bmean*bmean)*pixels
fsqsumg=(gstds*gstds+gmean*gmean)*pixels
fsqsumr=(rstds*rstds+rmean*rmean)*pixels
print ("fsqsum %.2f %.2f %.2f" % (fsqsumb,fsqsumg,fsqsumr))
fstdsb=math.sqrt(max(fsqsumb/nonzero-fbmean*fbmean,0))
fstdsg=math.sqrt(max(fsqsumg/nonzero-fgmean*fgmean,0))
fstdsr=math.sqrt(max(fsqsumr/nonzero-frmean*frmean,0))
print ("non-zero stds %.2f %.2f %.2f" % (fstdsb,fstdsg,fstdsr))
作为一个函数:
def fixMeans(self,means,stds,pixels,nonzero):
""" fix the zero based means to nonzero based see https://stackoverflow.com/a/58891531/1497139"""
gmean,bmean,rmean=means.flatten()
gstds,bstds,rstds=stds.flatten()
if Color.debug:
print ("means %.2f %.2f %.2f " % (gmean,bmean,rmean))
print ("stds %.2f %.2f %.2f " % (gstds,bstds,rstds))
factor=pixels/nonzero
fgmean=gmean*factor
fbmean=bmean*factor
frmean=rmean*factor
if Color.debug:
print ("non-zero means %.2f %.2f %.2f" % (fgmean,fbmean,frmean))
fsqsumb=(bstds*bstds+bmean*bmean)*pixels
fsqsumg=(gstds*gstds+gmean*gmean)*pixels
fsqsumr=(rstds*rstds+rmean*rmean)*pixels
if (Color.debug):
print ("fsqsum %.2f %.2f %.2f" % (fsqsumb,fsqsumg,fsqsumr))
fstdsb=math.sqrt(max(fsqsumb/nonzero-fbmean*fbmean,0))
fstdsg=math.sqrt(max(fsqsumg/nonzero-fgmean*fgmean,0))
fstdsr=math.sqrt(max(fsqsumr/nonzero-frmean*frmean,0))
if Color.debug:
print ("non-zero stds %.2f %.2f %.2f" % (fstdsb,fstdsg,fstdsr))
fixedmeans=fgmean,fbmean,frmean
fixedstds=fstdsb,fstdsg,fstdsr
return fixedmeans,fixedstds
推荐阅读
- batch-file - Windows批处理文件在if语句中的变量名上出错
- xaml - 用户在 UWP 中拖动 UI 元素
- python - 在类中设置可以在运行时修改的静态字典的 Pythonic 方法是什么?
- python - pandas 使用 groupby 加速多行计算
- angular - 如何在 Angular cli 6 中实现 Chalk?
- mysql - MYSQL:为三个字段的组合创建唯一索引以防止重复
- java - 从 Java 进程执行时跳过批处理文件中的暂停命令
- android - ViewPager 在 setImageResource 中返回 OOM
- linux - 新行上的邮件 bash 变量
- elasticsearch - 在 Vue 组件中使用 Axios...promise 出现在错误之后