mirror of https://github.com/emgucv/emgucv.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
364 lines
13 KiB
364 lines
13 KiB
//----------------------------------------------------------------------------
|
|
// Copyright (C) 2004-2019 by EMGU Corporation. All rights reserved.
|
|
//----------------------------------------------------------------------------
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Runtime.InteropServices;
|
|
using System.Windows.Forms;
|
|
using Emgu.CV;
|
|
using Emgu.CV.CvEnum;
|
|
using Emgu.Util.TypeEnum;
|
|
using Emgu.CV.Structure;
|
|
using System.Text;
|
|
|
|
namespace Emgu.CV.UI
|
|
{
|
|
internal partial class ImageProperty : UserControl
|
|
{
|
|
private HistogramViewer _histogramViewer;
|
|
|
|
/// <summary>
|
|
/// Create a ImageProperty control
|
|
/// </summary>
|
|
public ImageProperty()
|
|
{
|
|
InitializeComponent();
|
|
cSharpOperationView.Language = ProgrammingLanguage.CSharp;
|
|
cPlusPlusOperationView.Language = ProgrammingLanguage.CPlusPlus;
|
|
|
|
for (int i = 0; i < ImageBox.ZoomLevels.Length; i++)
|
|
{
|
|
zoomLevelComboBox.Items.Add(String.Format("{0}%", (int)(ImageBox.ZoomLevels[i] * 100)));
|
|
}
|
|
}
|
|
|
|
private ImageBox _imageBox;
|
|
|
|
/// <summary>
|
|
/// The parent imagebox for this property panel
|
|
/// </summary>
|
|
public ImageBox ImageBox
|
|
{
|
|
get { return _imageBox; }
|
|
set
|
|
{
|
|
_imageBox = value;
|
|
if (_imageBox != null)
|
|
{
|
|
//update control base on current functional mode
|
|
HandleFunctionalModeChange(this, new EventArgs());
|
|
|
|
//register event such that feature change in functional mode will also trigger an update to the control
|
|
_imageBox.OnFunctionalModeChanged += HandleFunctionalModeChange;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void HandleFunctionalModeChange(Object sender, EventArgs args)
|
|
{
|
|
bool zoom = (_imageBox.FunctionalMode & ImageBox.FunctionalModeOption.PanAndZoom) == ImageBox.FunctionalModeOption.PanAndZoom;
|
|
zoomLabel.Visible = zoomLevelComboBox.Visible = zoom;
|
|
}
|
|
|
|
private bool IsSubTypeOf(Type objType, Type typeToCheck)
|
|
{
|
|
while (objType != typeToCheck)
|
|
{
|
|
if (objType.IsGenericType && objType.GetGenericTypeDefinition() == typeToCheck)
|
|
{
|
|
return true;
|
|
}
|
|
objType = objType.BaseType;
|
|
if (objType == null)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public void SetImage(IImage image)
|
|
{
|
|
|
|
#region display the size of the image
|
|
if (image != null)
|
|
{
|
|
Size size = image.Size;
|
|
widthTextbox.Text = size.Width.ToString();
|
|
heightTextBox.Text = size.Height.ToString();
|
|
}
|
|
else
|
|
{
|
|
widthTextbox.Text = String.Empty;
|
|
heightTextBox.Text = string.Empty;
|
|
}
|
|
#endregion
|
|
|
|
#region display the color type of the image
|
|
if (image != null)
|
|
{
|
|
Type colorType = Reflection.ReflectIImage.GetTypeOfColor(image);
|
|
Object[] colorAttributes = colorType.GetCustomAttributes(typeof(ColorInfoAttribute), true);
|
|
if (colorAttributes.Length > 0)
|
|
{
|
|
ColorInfoAttribute info = (ColorInfoAttribute)colorAttributes[0];
|
|
typeOfColorTexbox.Text = info.ConversionCodename;
|
|
}
|
|
else
|
|
{
|
|
typeOfColorTexbox.Text = Properties.StringTable.Unknown;
|
|
}
|
|
|
|
Type colorDepth = Reflection.ReflectIImage.GetTypeOfDepth(image);
|
|
typeOfDepthTextBox.Text = colorDepth.Name;
|
|
}
|
|
else
|
|
{
|
|
typeOfColorTexbox.Text = string.Empty;
|
|
typeOfDepthTextBox.Text = string.Empty;
|
|
}
|
|
#endregion
|
|
|
|
#region check if image is a subclass of CvArr type
|
|
if (image != null)
|
|
{
|
|
Type imgType = image.GetType();
|
|
if (IsSubTypeOf(imgType, typeof(CvArray<>)))
|
|
_imageType = typeof(CvArray<>);
|
|
else if (IsSubTypeOf(imgType, typeof(Mat)))
|
|
_imageType = typeof(Mat);
|
|
else if (IsSubTypeOf(imgType, typeof(UMat)))
|
|
_imageType = typeof(UMat);
|
|
else
|
|
{
|
|
_imageType = null;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_imageType = null;
|
|
|
|
}
|
|
#endregion
|
|
|
|
UpdateHistogram();
|
|
UpdateZoomScale();
|
|
}
|
|
|
|
private Type _imageType = null;
|
|
//private bool isCvArray = true;
|
|
|
|
private String BufferToString<T>(T[] data, int numberOfChannels)
|
|
{
|
|
StringBuilder sb = new StringBuilder(String.Format("[{0}", data[0]));
|
|
for (int i = 1; i < numberOfChannels; i++)
|
|
sb.AppendFormat(",{0}", data[i]);
|
|
sb.Append("]");
|
|
return sb.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the mouse position over the image.
|
|
/// It also set the color intensity of the pixel on the image where is mouse is at
|
|
/// </summary>
|
|
/// <param name="location">The location of the mouse on the image</param>
|
|
public void SetMousePositionOnImage(Point location)
|
|
{
|
|
IImage img = _imageBox.DisplayedImage;
|
|
Size size = img.Size;
|
|
location.X = Math.Max(Math.Min(location.X, size.Width - 1), 0);
|
|
location.Y = Math.Max(Math.Min(location.Y, size.Height - 1), 0);
|
|
|
|
mousePositionTextbox.Text = location.ToString();
|
|
|
|
if (_imageType == typeof(CvArray<>))
|
|
{
|
|
MCvScalar scalar = CvInvoke.cvGet2D(img.Ptr, location.Y, location.X);
|
|
|
|
colorIntensityTextbox.Text = BufferToString(scalar.ToArray(), img.NumberOfChannels);
|
|
}
|
|
else if (_imageType == typeof(Mat))
|
|
{
|
|
Mat mat = img as Mat;
|
|
RenderIntensityForMat(mat, location);
|
|
}
|
|
else if (_imageType == typeof(UMat))
|
|
{
|
|
UMat umat = img as UMat;
|
|
using (Mat mat = umat.GetMat(AccessType.Read))
|
|
{
|
|
RenderIntensityForMat(mat, location);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
colorIntensityTextbox.Text = String.Empty;
|
|
}
|
|
}
|
|
|
|
private void RenderIntensityForMat(Mat mat, Point location)
|
|
{
|
|
byte[] raw = mat.GetRawData(location.Y, location.X);
|
|
|
|
if (mat.Depth == DepthType.Cv8U)
|
|
{
|
|
colorIntensityTextbox.Text = BufferToString(raw, mat.NumberOfChannels);
|
|
}
|
|
else if (mat.Depth == DepthType.Cv8S)
|
|
{
|
|
sbyte[] data = new sbyte[mat.NumberOfChannels];
|
|
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
|
Marshal.Copy(raw, 0, handle.AddrOfPinnedObject(), mat.ElementSize);
|
|
handle.Free();
|
|
colorIntensityTextbox.Text = BufferToString(data, data.Length);
|
|
}
|
|
else if (mat.Depth == DepthType.Cv16S)
|
|
{
|
|
GCHandle handle = GCHandle.Alloc(raw, GCHandleType.Pinned);
|
|
short[] data = new short[mat.NumberOfChannels];
|
|
Marshal.Copy(handle.AddrOfPinnedObject(), data, 0, data.Length);
|
|
handle.Free();
|
|
colorIntensityTextbox.Text = BufferToString(data, data.Length);
|
|
}
|
|
else if (mat.Depth == DepthType.Cv16U)
|
|
{
|
|
UInt16[] data = new UInt16[mat.NumberOfChannels];
|
|
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
|
Marshal.Copy(raw, 0, handle.AddrOfPinnedObject(), mat.ElementSize);
|
|
handle.Free();
|
|
colorIntensityTextbox.Text = BufferToString(data, data.Length);
|
|
}
|
|
else if (mat.Depth == DepthType.Cv32F)
|
|
{
|
|
GCHandle handle = GCHandle.Alloc(raw, GCHandleType.Pinned);
|
|
float[] floatData = new float[mat.NumberOfChannels];
|
|
Marshal.Copy(handle.AddrOfPinnedObject(), floatData, 0, floatData.Length);
|
|
handle.Free();
|
|
colorIntensityTextbox.Text = BufferToString(floatData, floatData.Length);
|
|
}
|
|
else if (mat.Depth == DepthType.Cv32S)
|
|
{
|
|
int[] data = new int[mat.NumberOfChannels];
|
|
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
|
Marshal.Copy(raw, 0, handle.AddrOfPinnedObject(), mat.ElementSize);
|
|
handle.Free();
|
|
colorIntensityTextbox.Text = BufferToString(data, data.Length);
|
|
}
|
|
else if (mat.Depth == DepthType.Cv64F)
|
|
{
|
|
GCHandle handle = GCHandle.Alloc(raw, GCHandleType.Pinned);
|
|
double[] doubleData = new double[mat.NumberOfChannels];
|
|
Marshal.Copy(handle.AddrOfPinnedObject(), doubleData, 0, doubleData.Length);
|
|
handle.Free();
|
|
colorIntensityTextbox.Text = BufferToString(doubleData, doubleData.Length);
|
|
}
|
|
else
|
|
{
|
|
colorIntensityTextbox.Text = String.Empty;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the description of the operation view
|
|
/// </summary>
|
|
public void SetOperations(List<Operation> operations)
|
|
{
|
|
cSharpOperationView.DisplayOperations(operations);
|
|
cPlusPlusOperationView.DisplayOperations(operations);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the frame rate
|
|
/// </summary>
|
|
public int FramesPerSecondText
|
|
{
|
|
set
|
|
{
|
|
fpsTextBox.Text = value.ToString();
|
|
}
|
|
}
|
|
|
|
public void UpdateZoomScale()
|
|
{
|
|
zoomLevelComboBox.Text = String.Format("{0}%", ImageBox.ZoomScale * 100);
|
|
}
|
|
|
|
private void clearOperationBtn_Click(object sender, EventArgs e)
|
|
{
|
|
_imageBox.ClearOperation();
|
|
}
|
|
|
|
private void popOperationButton_Click(object sender, EventArgs e)
|
|
{
|
|
_imageBox.PopOperation();
|
|
}
|
|
|
|
private void showHistogramButton_Click(object sender, EventArgs e)
|
|
{
|
|
if (_imageBox.DisplayedImage == null)
|
|
{
|
|
MessageBox.Show(Properties.StringTable.PleaseLoadAnImageFirst);
|
|
return;
|
|
}
|
|
|
|
if (_histogramViewer != null && _histogramViewer.Visible == false)
|
|
{
|
|
_histogramViewer.Dispose();
|
|
_histogramViewer = null;
|
|
}
|
|
|
|
if (_histogramViewer == null)
|
|
{
|
|
_histogramViewer = new HistogramViewer();
|
|
_histogramViewer.Show();
|
|
}
|
|
|
|
UpdateHistogram();
|
|
}
|
|
|
|
private void UpdateHistogram()
|
|
{
|
|
if (_histogramViewer != null && _histogramViewer.Visible)
|
|
{
|
|
IImage image = _imageBox.DisplayedImage;
|
|
|
|
if (image != null)
|
|
{
|
|
_histogramViewer.HistogramCtrl.ClearHistogram();
|
|
_histogramViewer.HistogramCtrl.GenerateHistograms(image, 256);
|
|
_histogramViewer.HistogramCtrl.Refresh();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void zoomLevelComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
if (_imageBox != null)
|
|
{
|
|
_imageBox.SetZoomScale(ImageBox.ZoomLevels[zoomLevelComboBox.SelectedIndex], Point.Empty);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clean up any resources being used.
|
|
/// </summary>
|
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (disposing && (components != null))
|
|
{
|
|
components.Dispose();
|
|
if (_histogramViewer != null)
|
|
{
|
|
_histogramViewer.Dispose();
|
|
_histogramViewer = null;
|
|
}
|
|
|
|
_imageBox.OnFunctionalModeChanged -= HandleFunctionalModeChange;
|
|
}
|
|
base.Dispose(disposing);
|
|
}
|
|
}
|
|
}
|