如何在opencv / python中识别具有特定形状的直方图

6
我希望能够将图片(来自杂志)分割成文本和图片部分。我有多个区域的直方图。我使用Python中的OpenCV(cv2)进行处理。
我想要识别这样的直方图。

http://matplotlib.sourceforge.net/users/image_tutorial-6.png

作为一个典型的文本区域形状,我该如何做到这一点?
编辑:非常感谢您迄今为止的帮助。
我将我的 ROIs 得到的直方图与我提供的样本直方图进行了比较:
hist = cv2.calcHist(roi,[0,1], None, [180,256],ranges)
compareValue = cv2.compareHist(hist, samplehist, cv.CV_COMP_CORREL)
print "ROI: {0}, compareValue: {1}".format(i,compareValue)

假设ROI 0、1、4和5是文本区域,ROI是图像区域,我得到的输出如下:
  • ROI:0,compareValue:1.0
  • ROI:1,compareValue:-0.000195522081574 <--- 分类错误
  • ROI:2,compareValue:0.0612670248952
  • ROI:3,compareValue:-0.000517370176887
  • ROI:4,compareValue:1.0
  • ROI:5,compareValue:1.0
我该怎么做才能避免错误分类?对于一些图像,误分类率约为30%,这太高了。(我还尝试了CV_COMP_CHISQR、CV_COMP_INTERSECT、CV_COMP_BHATTACHARYY和(hist*samplehist)。sum(),但它们也提供了错误的compareValues)
2个回答

9
如果您想绘制直方图,我已经向OpenCV提交了一个Python示例,您可以从这里获取:http://code.opencv.org/projects/opencv/repository/entry/trunk/opencv/samples/python2/hist.py。它用于绘制两种类型的直方图。第一种适用于彩色和灰度图像,如此处所示:http://opencvpython.blogspot.in/2012/04/drawing-histogram-in-opencv-python.html。第二种是专门针对灰度图像的,与问题中的图像相同。我将展示第二种及其修改。考虑下面的完整图像: enter image description here我们需要绘制如您所示的直方图。请查看以下代码:
import cv2
import numpy as np

img = cv2.imread('messi5.jpg')
mask = cv2.imread('mask.png',0)
ret,mask = cv2.threshold(mask,127,255,0)

def hist_lines(im,mask):
    h = np.zeros((300,256,3))
    if len(im.shape)!=2:
        print "hist_lines applicable only for grayscale images"
        #print "so converting image to grayscale for representation"
        im = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
    hist_item = cv2.calcHist([im],[0],mask,[256],[0,255])
    cv2.normalize(hist_item,hist_item,0,255,cv2.NORM_MINMAX)
    hist=np.int32(np.around(hist_item))
    for x,y in enumerate(hist):
        cv2.line(h,(x,0),(x,y),(255,255,255))
    y = np.flipud(h)
    return y

histogram = hist_lines(img,None)

以下是我们得到的直方图。请记住,这是整个图像的直方图。因此,我们对掩码使用了None

enter image description here

现在我想找到图像某一部分的直方图。OpenCV的直方图函数提供了掩码功能。对于普通直方图,您应该将其设置为None。否则,您必须指定掩码。
掩码是一个8位图像,其中白色表示应该用于直方图计算的区域,黑色表示不应该用于直方图计算的区域。
因此,我使用了如下的掩码(使用画图创建,您需要根据自己的目的创建自己的掩码)。

enter image description here

我将代码的最后一行更改为以下内容:
histogram = hist_lines(img,mask)

现在看下面的区别:

enter image description here

(请记住,值已经标准化,因此显示的值不是实际像素计数,而是标准化为255。您可以根据需要进行更改。)

编辑:

我想我误解了你的问题。你需要比较直方图,对吗?

如果这就是你想要的,你可以使用cv2.compareHist函数。

有一个关于这个问题的C++官方教程。你可以在这里找到相应的Python代码。


@Abid Rahman K. 什么是掩码的作用?我看到一些函数中有提到掩码。它是一种可以设置图像ROI的方式吗? - Mzk
是的,通常roi是矩形区域,但使用掩码,您可以采用任何形状。请查看我的博客中有关轮廓的部分以获取更多详细信息。Opencvpython.blogspot.com - Abid Rahman K

3

您可以使用简单的相关度量。

  • 确保您计算的直方图和参考直方图已经归一化(即表示概率)

  • 对于每个直方图计算(假设myRef和myHist是numpy数组):

    metric = (myRef * myHist).sum()

  • 该度量标准衡量直方图与您的参考直方图相似程度。


这是一个非常有趣的想法。但是你所说的 myRef 到底是什么意思?它是另一个直方图还是和 myHist 一样大小的数组?还是任意的 numpy 数组? - samkhan13
@samkhan13 是的,myRef 是我们想要比较的直方图。 - Simon Bergot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接