如何使用EmguCV和C#绘制直方图

时间:2011-11-20 21:21:09

标签: c# emgucv

我需要绘制两种类型的直方图,即单维和立体。 我是EMGU的新手,我在网上找到的所有样本都是C ++或C.有没有使用C#和Emgucv的样本?

感谢您的帮助。

5 个答案:

答案 0 :(得分:7)

以下代码将分割RED GREEN和BLUE Histogram数据,并将它们放入浮动数组中,以满足您的任何需要。

float[] BlueHist;
float[] GreenHist;
float[] RedHist;

Image<Bgr, Byte> img = new Image<Bgr, byte>("ImageFileName");

DenseHistogram Histo = new DenseHistogram(255, new RangeF(0, 255));

Image<Gray, Byte> img2Blue = img[0];
Image<Gray, Byte> img2Green = img[1];
Image<Gray, Byte> img2Red = img[2];


Histo.Calculate(new Image<Gray, Byte>[] { img2Blue }, true, null);
//The data is here
//Histo.MatND.ManagedArray
BlueHist = new float[256];
Histo.MatND.ManagedArray.CopyTo(BlueHist, 0);

Histo.Clear();

Histo.Calculate(new Image<Gray, Byte>[] { img2Green }, true, null);
GreenHist = new float[256];
Histo.MatND.ManagedArray.CopyTo(GreenHist, 0);

Histo.Clear();

Histo.Calculate(new Image<Gray, Byte>[] { img2Red }, true, null);
RedHist = new float[256];
Histo.MatND.ManagedArray.CopyTo(RedHist, 0);

这将执行灰度直方图:

float[] GrayHist;

Image<Gray, Byte> img_gray = new Image<Gray, byte>("ImageFileName");

Histo.Calculate(new Image<Gray, Byte>[] { img_gray }, true, null);
//The data is here
//Histo.MatND.ManagedArray
GrayHist = new float[256];
Histo.MatND.ManagedArray.CopyTo(GrayHist, 0);

希望这有帮助,

干杯,

克里斯

[编辑]

要绘制直方图,您需要使用自己的或者设计的控件,例如Zedgraph(这是随EMGU提供的),这是一篇关于codeproject的非常好的文章,显示了它的用途。

http://www.codeproject.com/KB/graphics/zedgraph.aspx

干杯

克里斯

答案 1 :(得分:3)

在Emgu中显示直方图非常简单有趣。只需在表单上创建一个histogramBox控件,然后在循环中调用它即可完成。

        histogramBox1.ClearHistogram();
        histogramBox1.GenerateHistograms(frame, 256);
        histogramBox1.Refresh();

答案 2 :(得分:0)

立体直方图

Image<Bgr, Byte>[] inp = new Image<Bgr, byte>("fileName.jpg");
int nBins = 256;
DenseHistogram hist = new DenseHistogram(new int[] { nBins, nBins, nBins }, new RangeF[] { new RangeF(0, 255), new RangeF(0, 255), new RangeF(0, 255) });
hist.Calculate(inp.Split(), false, null);

// To get value of single bin
int b = 255; int g = 0; int r = 0;  //blue
int count = Convert.ToInt32(hist.MatND.ManagedArray.GetValue(b, g, r));  //count = no of pixels in color Bgr(b,g,r)

//To get all values in a single array
List<Tuple<Bgr, int>> histVal = new List<Tuple<Bgr, int>>(nBins * nBins * nBins);
for (int i = 0; i < nBins; i++)
    for (int j = 0; j < nBins; j++)
        for (int k = 0; k < nBins; k++)
            histVal.Add(new Tuple<Bgr, int>(new Bgr(i, j, k), Convert.ToInt32(hist.MatND.ManagedArray.GetValue(i, j, k))));

单维直方图

int nBins = 256;
float[] valHist = new float[nBins];
Image<Gray, Byte>[] inp = new Image<Gray, byte>("fileName.jpg");
DenseHistogram hist = new DenseHistogram(nBins, new RangeF(0, 255));
hist.Calculate(new Image<Gray, Byte>[] { inp }, true, null);
hist.MatND.ManagedArray.CopyTo(valHist,0);

答案 3 :(得分:0)

请务必按照以下步骤将Emgu.CV.UI.dll添加到Windows窗体中的工具箱中,以便使用Emgu CV提供的所有Windows窗体控件(包括HistogramBox。)

首先,您需要在设计器视图中打开表单。在工具箱中,右键单击“常规”空白区域。柱。这应该会弹出一个选择菜单,其中包括选择项目&#39;选择可用,见下图。

Designer Form View

之后,点击&#39;选择项目&#39 ;;你会看到一个&#39;选择工具箱项目&#39;对话。从那里点击“浏览...”#39;对话框右下角的按钮。

enter image description here

选择&#39; Emgu.CV.UI.dll&#39;文件来自&#39; Open&#39;对话框,单击“打开”按钮。按钮。 现在您应该注意到ImageBox控件已添加到“选择工具箱项目”中。对话。点击“确定”。然后你应该注意到你的工具箱中添加了以下控件(适用于Emgu的3.10版本。其他一些版本的Emgu可能有其他控件或缺少下面提到的控件。)

  • HistogramBox
  • ImageBox
  • MatrixBox
  • PanAndZoomPictureBox。

ToolBoxControls

然后,您应该能够拖放到您的表单,因为您认为Emgu CV已经构建了它的Windows窗体控件。或者您应该能够以编程方式使用它们:

Form frm = new Form();
var img = CvInvoke.Imread(this.PictureBox.ImageLocation, Emgu.CV.CvEnum.LoadImageType.Grayscale).ToImage<Gray, Byte>();

HistogramBox histo = new HistogramBox();

histo.ClearHistogram();
histo.GenerateHistograms(img, 256);
histo.Dock = DockStyle.Fill;
histo.Refresh();

frm.Controls.Add(histo);

frm.ShowDialog(); 

这个答案的灵感来自Add Image Box Control教程。

答案 4 :(得分:0)

在这里你可以在MVVM WPF方法的上下文中找到使用Emgucv绘制灰度图像直方图的答案..希望它对某人有用

MainWindow.xaml

这是视图

<Window x:Class="Histogram.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:vm="clr-namespace:HistogramAndOverlayingMVVM.ViewModel"
    xmlns:local="clr-namespace:Histogram"
    mc:Ignorable="d"
    Title="MainWindow" WindowState="Maximized">
<Window.DataContext>
    <vm:MainWindowViewModel/>
</Window.DataContext>
<Grid>
    <Button Content="LoadImage" Command="{Binding OpenImg}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="Auto" Height="Auto" Margin="31,5,0,0" />
    <Button Content="Histogram" Command="{Binding Histogram}"HorizontalAlignment="Left" Margin="135,5,0,0" VerticalAlignment="Top" Width="Auto" Height="Auto"/>
    <Image Source="{Binding Image.Source}" HorizontalAlignment="Left" Height="346" Margin="9,39,0,0" VerticalAlignment="Top" Width="546"/>
    <Image Source="{Binding Hist.Source}" HorizontalAlignment="Left" Height="346" Margin="569,39,-353.4,0" VerticalAlignment="Top" Width="546"/>
</Grid></Window>

MainWindowViewModel.cs

这是viewmodel类

class MainWindowViewModel
{
    public ICommand OpenImg { get; set; }
    Image<Bgr, byte> imgInput;

    Histogram his = new Histogram();

    public MainWindowViewModel()
    {
        OpenImg = new RelayCommand(openImg, (obj) => true);
        _image = new System.Windows.Controls.Image();
        _hist = new System.Windows.Controls.Image();
    }
    private void openImg(object obj = null)
    {
        OpenFileDialog op = new OpenFileDialog();
        op.Title = "Select a picture";
        op.Filter = "All supported graphics|*.jpg;*.jpeg;*.png;*.bmp;*.tiff|" +
          "JPEG (*.jpg;*.jpeg)|*.jpg;*.jpeg|" +
          "Portable Network Graphic (*.png)|*.png";
        if (op.ShowDialog() == true)
        {
           string ImgPath = op.FileName;
            imgInput = new Image<Bgr, byte>(ImgPath);
            Image.Source = BitmapSourceConvert.ToBitmapSource(imgInput);

        }
    }
    private System.Windows.Controls.Image _image;
    public System.Windows.Controls.Image Image
    {
        get { return _image; }
        set
        {
            _image = value;
        }
    }

    private ICommand _histogram;
    public ICommand Histogram
    {
        set { _histogram = value; }
        get
        {
            if(_histogram == null)
            {
                _histogram = new RelayCommand(param => DrawHistogram((EventArgs)param));
            }
            return _histogram;
        }
    }
    private void DrawHistogram(EventArgs e)
    {
        Bitmap img;
        img = his.ApplyHistogram(imgInput);
        Hist.Source = BitmapSourceConvert.BitmapToImageSource(img);            
    }
    private System.Windows.Controls.Image _hist;
    public System.Windows.Controls.Image Hist
    {
        get { return _hist; }
        set
        {
            _hist = value;
        }
    }
}

Histogram.cs

这是模型类

public class Histogram
{
    public Bitmap ApplyHistogram(Image<Bgr,byte> imgInput)
    {
        Image<Gray, Byte> src = imgInput.Convert<Gray, byte>();

        DenseHistogram hist = new DenseHistogram(256, new RangeF(0.0f, 255f));
        hist.Calculate(new Image<Gray, byte>[] { src }, true, null);

        // Get the max value of histogram
        double minVal = 0.0;
        double maxVal = 0.0;
        Point minLoc = new Point();
        Point maxLoc = new Point();

        CvInvoke.MinMaxLoc(hist, ref minVal, ref maxVal, ref minLoc, ref maxLoc);

        // Scale histogram
        const int width = 256;
        const int height = 250;
        var histData = hist.GetBinValues();

        Bitmap histo = DrawHistogram(maxVal, width, height, histData);
        return histo;           
    }       
    private static Bitmap DrawHistogram(double maxVal, int width, int height, float[] histData)
    {
        Bitmap histo = new Bitmap(width, height);
        Graphics g = Graphics.FromImage(histo);
        g.Clear(SystemColors.Window);
        Pen penGray = new Pen(Brushes.DarkGray);

        for (var i = 0; i < histData.GetLength(0); i++)
        {
            var val = (float)histData.GetValue(i);
            val = (float)(val * (maxVal != 0 ? height / maxVal : 0.0));

            Point s = new Point(i, height);
            Point e = new Point(i, height - (int)val);
            g.DrawLine(penGray, s, e);
        }
        return histo;
    }
}