Skip to content

Commit 1c867f9

Browse files
committed
Initial commit
0 parents  commit 1c867f9

File tree

7 files changed

+300
-0
lines changed

7 files changed

+300
-0
lines changed

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# histogramRangeSelector
2+
3+
Version: 1.0
4+
5+
![histogramRangeSelector](/histogramRangeSelector/example_histogramRangeSelector.png)
6+
7+
This component is designed to allow specification of minimum and maximum values for an intensity image, or independently for the RGB channels of an image.
8+
It features a histogram for showing the intensity data and editfields with accompanying lines for setting the minimum and maximum.
9+
When the values change, the MinChanged/MaxChanged events fire.
10+
11+
How to use:
12+
```
13+
c = histogramRangeSelector; % create the component
14+
15+
im = imread('myimage.png'); % read an image
16+
[n,x]=histcounts(im(:),0:255); % collect histogram data
17+
set(c,'HistogramBinEdges',x,'HistogramBinCounts',n);
18+
19+
20+
c.MinChangedFcn=@myMinChangedFunction;
21+
c.MaxChangedFcn=@myMaxChangedFunction;
22+
```
23+
24+
Some additional demo apps are included: histogramRangeSelectorDemo which lets you set the RGB ranges for an image, and histogramRangeSelectorWebcamDemo which subclasses histogramRangeSelectorDemo and uses your webcam for the image data. Note that this requires MATLAB Support Package for USB Webcams
25+
26+
![histogramRangeSelector](/histogramRangeSelector/example_histogramRangeSelectorWebcamDemo.png)

SECURITY.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Reporting Security Vulnerabilities
2+
3+
If you believe you have discovered a security vulnerability, please report it to
4+
[security@mathworks.com](mailto:security@mathworks.com). Please see
5+
[MathWorks Vulnerability Disclosure Policy for Security Researchers](https://www.mathworks.com/company/aboutus/policies_statements/vulnerability-disclosure-policy.html)
6+
for additional information.

example_histogramRangeSelector.png

2.54 KB
Loading

histogramRangeSelector.m

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
classdef histogramRangeSelector < matlab.ui.componentcontainer.ComponentContainer
2+
% histogramRangeSelector Custom component for selecting a range absed on
3+
% a histogram.
4+
%
5+
% histogramRangeSlector is a custom component to place into an app to
6+
% allow app users to select a range based on a set of values. It shows a
7+
% histogram and allows users to select a minimum and maximum value based
8+
% on the histogram. When these values are selected, the MinChangedFcn and
9+
% MaxChangedFcn callbacks execute.
10+
%
11+
% Use the left and right mouse buttons to interactively select minimum
12+
% and maximum values, or enter them in the edit fields within the
13+
% component.
14+
%
15+
% Properties:
16+
% ===========
17+
% HistogramBinEdges, HistogramBinCounts : the edges and counts to be
18+
% displayed in the histogram. The HISTCOUNTS function is useful for
19+
% getting these values.
20+
%
21+
% Min, Max : The currently selected minimum and maximum values.
22+
%
23+
% Color : Color for the histogram display
24+
%
25+
% MinChangedFcn, MaxChangedFcn : callback functions that execute when the
26+
% Min and Max values change.
27+
28+
% Copyright 2021 The MathWorks, Inc.
29+
30+
properties
31+
HistogramBinEdges (1,:) double = []
32+
HistogramBinCounts (1,:) double = []
33+
Min (1,1) double = 0
34+
Max (1,1) double = 255
35+
Color {validatecolor} = [.6 .6 .6]
36+
end
37+
38+
properties(Access=private, Transient)
39+
Grid matlab.ui.container.GridLayout
40+
Ax matlab.ui.control.UIAxes
41+
HistBar matlab.graphics.chart.primitive.Histogram
42+
MinLine matlab.graphics.chart.decoration.ConstantLine
43+
MaxLine matlab.graphics.chart.decoration.ConstantLine
44+
MinEdit matlab.ui.control.EditField
45+
MaxEdit matlab.ui.control.EditField
46+
47+
LeftPatch matlab.graphics.primitive.Patch
48+
RightPatch matlab.graphics.primitive.Patch
49+
50+
HistogramDirty = true;
51+
end
52+
53+
events (HasCallbackProperty, NotifyAccess=protected)
54+
MinChanged
55+
MaxChanged
56+
end
57+
58+
methods (Access=protected)
59+
function setup(obj)
60+
% Create Top-Level grid, and Uiaxes that will hold Histogram
61+
obj.Grid = uigridlayout(obj, [2 1], 'RowHeight', {'1x' 22}, ...
62+
'Padding',0, 'RowSpacing', 0);
63+
obj.Ax = uiaxes(obj.Grid, 'XTick', [], 'YTick', [], ...
64+
'Box', 'on', 'XLim', [0 255]);
65+
66+
% Disable default interactivity, and enable custom interaction
67+
disableDefaultInteractivity(obj.Ax)
68+
obj.Ax.ButtonDownFcn = @(~,~)obj.buttoncallback;
69+
70+
% Disable toolbar
71+
obj.Ax.Toolbar = [];
72+
73+
% Add the histogram to the axes and patches to 'grey' out the
74+
% region outside of the min/max
75+
obj.HistBar = histogram(obj.Ax, 'HitTest', 'off', ...
76+
'EdgeColor', 'none', 'FaceAlpha', 1, 'FaceColor', obj.Color);
77+
obj.LeftPatch = patch(obj.Ax, 'FaceColor', 'w', ...
78+
'FaceAlpha', .5, 'EdgeColor', 'none', 'HitTest', 'off');
79+
obj.RightPatch = patch(obj.Ax, 'FaceColor', 'w', ...
80+
'FaceAlpha', .5, 'EdgeColor', 'none', 'HitTest', 'off');
81+
82+
% Add the minimum and maximum lines
83+
obj.MinLine = xline(obj.Ax, 0, 'LineWidth', 1);
84+
obj.MaxLine = xline(obj.Ax, 255, 'LineWidth', 1);
85+
86+
% Create a nested grid to hold the edit fields
87+
lowergrid = uigridlayout(obj.Grid, [1 3], ...
88+
'ColumnWidth', {45 '1x' 45}, 'Padding', 0);
89+
obj.MinEdit = uieditfield(lowergrid, 'Value', string(obj.Min), ...
90+
'ValueChangedFcn', @obj.chgMinEdit);
91+
obj.MaxEdit = uieditfield(lowergrid, 'Value', string(obj.Max), ...
92+
'ValueChangedFcn', @obj.chgMaxEdit);
93+
obj.MaxEdit.Layout.Column = 3;
94+
end
95+
96+
function update(obj)
97+
% Only update the histogram if there's data, and it's changed
98+
if ~isempty(obj.HistogramBinEdges) && obj.HistogramDirty
99+
set(obj.HistBar, 'BinEdges', obj.HistogramBinEdges, ...
100+
'BinCounts', obj.HistogramBinCounts)
101+
obj.Ax.XLim = obj.HistogramBinEdges([1 end]);
102+
obj.Ax.YLim = [0 max(obj.HistogramBinCounts)];
103+
% Make sure the current min and max fit in the new
104+
% histogram edges:
105+
obj.Min = max(obj.Min, obj.Ax.XLim(1));
106+
obj.Max = min(obj.Max, obj.Ax.XLim(2));
107+
end
108+
obj.HistBar.FaceColor=obj.Color;
109+
% Set the 'greyed' out regions using xlim and ylim and Min/Max
110+
xl = obj.Ax.XLim;
111+
yl = obj.Ax.YLim;
112+
obj.LeftPatch.XData = [xl(1) xl(1) obj.Min obj.Min];
113+
obj.LeftPatch.YData = [yl(1) yl(2) yl(2) yl(1)];
114+
115+
obj.RightPatch.XData = [xl(2) xl(2) obj.Max obj.Max];
116+
obj.RightPatch.YData = [yl(1) yl(2) yl(2) yl(1)];
117+
end
118+
end
119+
120+
methods
121+
function set.Min(obj, val)
122+
obj.MinLine.Value = val;
123+
obj.MinEdit.Value = string(val);
124+
obj.Min = val;
125+
notify(obj, 'MinChanged')
126+
end
127+
function set.Max(obj, val)
128+
obj.MaxLine.Value = val;
129+
obj.MaxEdit.Value = string(val);
130+
obj.Max = val;
131+
notify(obj, 'MaxChanged')
132+
end
133+
function set.HistogramBinEdges(obj, val)
134+
obj.HistogramBinEdges = val;
135+
obj.HistogramDirty = true;
136+
end
137+
function set.HistogramBinCounts(obj, val)
138+
obj.HistogramBinCounts = val;
139+
obj.HistogramDirty = true;
140+
end
141+
end
142+
143+
methods (Access=private)
144+
function buttoncallback(obj)
145+
146+
cx = obj.Ax.CurrentPoint(1);
147+
148+
% Get the figure ancestor to determine whether it was a left or
149+
% right click.
150+
fig=ancestor(obj.Ax,'figure');
151+
but=fig.SelectionType;
152+
153+
if strcmp(but,'normal')
154+
% Left click changes Min, but clamp it to the range of the
155+
% histogram and the current Max.
156+
obj.Min = min(max(cx, obj.Ax.XLim(1)), obj.Max);
157+
elseif strcmp(but,'alt')
158+
% Right click changes Max, but clamp it to the range of the
159+
% histogram and the current Min.
160+
obj.Max = max(min(cx, obj.Ax.XLim(2)), obj.Min);
161+
end
162+
end
163+
function chgMinEdit(obj, ~, event)
164+
% Callback for user change to Min editfield: validate and set
165+
val = str2double(event.Value);
166+
if val >= obj.Max || val < obj.Ax.XLim(1)
167+
obj.MinEdit.Value = event.PreviousValue;
168+
else
169+
obj.Min = val;
170+
end
171+
end
172+
function chgMaxEdit(obj,~,event)
173+
% Callback for user change to Max editfield: validate and set
174+
val = str2double(event.Value);
175+
if val <= obj.Min || val > obj.Ax.XLim(2)
176+
obj.MaxEdit.Value = event.PreviousValue;
177+
else
178+
obj.Max = val;
179+
end
180+
end
181+
end
182+
end

histogramRangeSelectorDemo.m

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
function histogramRangeSelectorDemo
2+
% histogramRangeSelectorDemo: Function to call histogramRangeSelectorDemoApp
3+
% and apply some image data.
4+
5+
% Copyright 2021 The MathWorks, Inc.
6+
7+
im = imread('peppers.png');
8+
h = histogramRangeSelectorDemoApp;
9+
h.setImageData(im);
10+
end

histogramRangeSelectorDemoApp.m

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
classdef histogramRangeSelectorDemoApp < handle
2+
% histogramRangeSelectorDemoApp: A small app that demonstrates the
3+
% histogramRangeSelector custom component by displaying an image and offering
4+
% interactive control of RGB min/max.
5+
6+
% Copyright 2021 The MathWorks, Inc.
7+
8+
properties (Transient, Access=protected)
9+
fig
10+
lay
11+
ax
12+
im
13+
14+
hrs (1,3) histogramRangeSelector
15+
ImageData (:,:,3) uint8
16+
end
17+
18+
19+
methods
20+
function obj=histogramRangeSelectorDemoApp
21+
obj.fig = uifigure;
22+
obj.lay = uigridlayout(obj.fig, [4 2], ...
23+
'ColumnWidth', {'1x' 150}, ...
24+
'RowHeight',{100 100 100 'fit'});
25+
26+
obj.ax=uiaxes(obj.lay,'XTick',[],'YTick',[],'Box','on');
27+
obj.ax.Layout.Row=[1 4];
28+
obj.im=image(obj.ax,zeros(0,0,3,'uint8'));
29+
axis(obj.ax,'image')
30+
31+
obj.hrs(1)=histogramRangeSelector(obj.lay,'Color',[1 0 0]);
32+
obj.hrs(1).Layout.Row=1;
33+
obj.hrs(2)=histogramRangeSelector(obj.lay,'Color',[0 1 0]);
34+
obj.hrs(2).Layout.Row=2;
35+
obj.hrs(3)=histogramRangeSelector(obj.lay,'Color',[0 0 1]);
36+
obj.hrs(3).Layout.Row=3;
37+
38+
for i = 1:3
39+
obj.hrs(i).MinChangedFcn=@(~,~)obj.rescaleColors;
40+
obj.hrs(i).MaxChangedFcn=@(~,~)obj.rescaleColors;
41+
end
42+
end
43+
function setImageData(obj,imdata)
44+
% update histograms
45+
for i = 1:3
46+
[obj.hrs(i).HistogramBinCounts,obj.hrs(i).HistogramBinEdges] = histcounts(imdata(:,:,i),0:255);
47+
end
48+
49+
% update ImageData
50+
obj.ImageData=imdata;
51+
52+
% Rescale colors (which will set the Image's CData
53+
obj.rescaleColors;
54+
end
55+
end
56+
methods (Access=private)
57+
function rescaleColors(obj)
58+
c=obj.ImageData;
59+
for i = 1:3
60+
c(:,:,i)=rescale(c(:,:,i),0,255,'InputMin',obj.hrs(i).Min,'InputMax',obj.hrs(i).Max);
61+
end
62+
obj.im.CData=c;
63+
end
64+
end
65+
66+
end

license.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Copyright (c) 2020, The MathWorks, Inc.
2+
All rights reserved.
3+
4+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5+
6+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8+
3. In all cases, the software is, and all modifications and derivatives of the software shall be, licensed to you solely for use in conjunction with MathWorks products and service offerings.
9+
10+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

0 commit comments

Comments
 (0)