How to put show an outline for each chart series in a RadChart? - charts

I'm trying to customize the appearance of an ASP Web Forms RadChart where the series have FillType = Solid while still allowing visibility of the lesser point values behind larger ones. What I really want is each series to have an outline placed on top of all the fills (basically the effect of having a ChartSeriesType.Line on top of a ChartSeriesType.Area).
I've experimented with setting LineAppearance.Shadow, color transparency, and combinations of those but it's still too difficult to discern background series values.
Is there not a simple way to turn on an outline for each series when using a solid fill? OR to set the transparency of the background fill only, not the edges?
Note the transparency in the above image. I'm afraid allowing more transparency improves the visibility of background values but results in a horrible collection of pastel colors.

I suggest you to go through telerik documentation page RadControls for ASP.NET AJAX Documentation -Styling Chart Elements and this nice example Creating RadChart Programmatically - more complex example.
Code snippet:
// Define chart and titleRadChart radChart = new RadChart();
radChart.ChartTitle.TextBlock.Text = "My RadChart";
radChart.ChartTitle.TextBlock.Appearance.TextProperties.Color = System.Drawing.Color.Blue;
// Define chart series
ChartSeries chartSeries = new ChartSeries();
chartSeries.Appearance.LabelAppearance.Visible = false;
chartSeries.Name = "GDP";
chartSeries.Type = ChartSeriesType.Line;
chartSeries.Appearance.LineSeriesAppearance.Color = System.Drawing.Color.BlueViolet;
// Define the items in the series
chartSeries.AddItem(1);
chartSeries.AddItem(1.5);
chartSeries.AddItem(2.0);
chartSeries.AddItem(2.5);
chartSeries.AddItem(3.5);
// visually enhance the datapoints
chartSeries.Appearance.PointMark.Dimensions.AutoSize = false;
chartSeries.Appearance.PointMark.Dimensions.Width = 5;
chartSeries.Appearance.PointMark.Dimensions.Height = 5;
chartSeries.Appearance.PointMark.FillStyle.MainColor = System.Drawing.Color.Black;
chartSeries.Appearance.PointMark.Visible = true;
// Define chart series
ChartSeries chartSeries2 = new ChartSeries();
chartSeries2.Appearance.LabelAppearance.Visible = false;
chartSeries2.Name = "GNP";
chartSeries2.Type = ChartSeriesType.Line;
chartSeries2.Appearance.LineSeriesAppearance.Color = System.Drawing.Color.Green;
// Define the items in the series
chartSeries2.AddItem(2);
chartSeries2.AddItem(3);
chartSeries2.AddItem(3.5);
chartSeries2.AddItem(4);
chartSeries2.AddItem(4.5);
// visually enhance the data points
chartSeries2.Appearance.PointMark.Dimensions.AutoSize = false;
chartSeries2.Appearance.PointMark.Dimensions.Width = 5;
chartSeries2.Appearance.PointMark.Dimensions.Height = 5;
chartSeries2.Appearance.PointMark.FillStyle.MainColor = System.Drawing.Color.Black;
chartSeries2.Appearance.PointMark.Visible = true;
// set the plot area gradient background fill
radChart.PlotArea.Appearance.FillStyle.FillType = Telerik.Charting.Styles.FillType.Gradient;
radChart.PlotArea.Appearance.FillStyle.MainColor = System.Drawing.Color.FromArgb(65, 201, 254);
radChart.PlotArea.Appearance.FillStyle.SecondColor = System.Drawing.Color.FromArgb(0, 107, 186);
// Set text and line for X axis
radChart.PlotArea.XAxis.AxisLabel.TextBlock.Text = "Years";
radChart.PlotArea.XAxis.AxisLabel.TextBlock.Appearance.TextProperties.Color = System.Drawing.Color.Red;
radChart.PlotArea.XAxis.Appearance.Width = 3;
radChart.PlotArea.XAxis.Appearance.Color = System.Drawing.Color.Red;
// Set text and line for Y axis
radChart.PlotArea.YAxis.AxisLabel.TextBlock.Text = "%";
radChart.PlotArea.YAxis.AxisLabel.TextBlock.Appearance.TextProperties.Color = System.Drawing.Color.Red;
radChart.PlotArea.YAxis.Appearance.Width = 3;
radChart.PlotArea.YAxis.Appearance.Color = System.Drawing.Color.Red;
// Add the series to the chart, chart to page.radChart.Series.Add(chartSeries);radChart.Series.Add(chartSeries2);this.Page.Controls.Add(radChart)
Hope this help..

Related

amCharts 4 - Has anyone successfully added minor ticks to an axis?

I have a Guage chart that is scaled from 0 to 120. Automatically, major ticks are drawn every 10 points and there are no minor ticks. I would like to add minor ticks that increment by 2. Thus far I have not been able to find a way to do this. Can anyone please provide some guidance or even better a solution?
In amCharts 3, configuring minor ticks is clearly documented. However, in amCharts 4 this feature has disappeared and a more generic method appears to be used. However, I have not found any documentation or demo that helps to solve this simple problem.
If you want to play with code, this demo is a great place to start.
Thanks!!
The below solution works. It requires drawing a second axis and adjusting the scale range and the spacing using minGridDistance. The results from the code below is:
Simple gauge chart based on the below code
I did find that minGridDistance did not behave predictably across all scale ranges. For a range of values from 0 to a maximum range of 120, minGridDistance did not work. However, for a maximum range of 60 (in the example below) and for 500, minGridDistance worked fine. Thus, some experimentation is required.
/**
* minor ticks
*/
var axis = chart.xAxes.push(new am4charts.ValueAxis());
axis.min = 0;
axis.max = 60;
axis.strictMinMax = true;
axis.renderer.radius = am4core.percent(100);
axis.renderer.line.strokeOpacity = 1;
axis.renderer.inside = false;
axis.renderer.labels.template.disabled = true;
axis.renderer.ticks.template.disabled = false;
axis.renderer.ticks.template.strokeOpacity = 1;
axis.renderer.ticks.template.length = 8;
axis.renderer.grid.template.disabled = true;
axis.renderer.minGridDistance = 1;
/**
* major ticks and labels
*/
var axis2 = chart.xAxes.push(new am4charts.ValueAxis());
axis2.min = 0;
axis2.max = 120;
axis2.strictMinMax = true;
axis2.renderer.labels.template.disabled = false;
axis2.renderer.ticks.template.disabled = false;
axis2.renderer.ticks.template.length = 13;
axis2.renderer.ticks.template.strokeOpacity = 1;
axis2.renderer.grid.template.disabled = true;

Merging neighboring connected components with different labels

Consider the following image:
On the left, let's say I have 3 labels. The background = 1, the black = 2, the orange = 3. What I want to do is be able to first identify all connected components that are orange, then if there are black objects touching the orange, then I'd like to convert this to orange as well.
I know the following steps:
Assume the labeled image is called labeled. I do orange = labeled == 3
CC = bwconncomp(orange);
But from here, I'm not sure how I can check if any of the black components are touching the orange. Once I know which black components are touching the orange, I can do the following: RP = regionprops(black, 'PixelIdxList'); labeled(RP(index).PixelIdxList) = 3;
To test code: here is an example input and output generation:
%input matrix
I = zeros([8 8]);
I(1:5, 1:5) = 1;
I(2:4, 3:7) = 2;
I(7:8, 1:2) = 1;
I(7:8, 7:8) = 2;
I
%output
O = zeros([8 8]);
O(1:5, 1:5) = 1;
O(2:4, 3:7) = 1;
O(7:8, 1:2) = 1;
O(7:8, 7:8) = 2;
O
You can do it as follows. Let target denote the target value, corresponding to orange.
Identify regions defined as connected components without regard to color, using bwlabel.
For each region, if it contains at least a pixel equal to target, set the whole region to target.
target = 1; % value corresponding to orange
O = I;
[regions, numRegions] = bwlabel(I);
for regionId = 1:numRegions
ind = regions==regionId;
if any(I(ind)==target)
O(ind) = target;
end
end
This can be quite simply solved using imreconstruct. This function, for binary (logical) inputs, does a flood fill. The idea is to find an mask image (the orange and the black regions together) and a marker (or seed) image (the orange regions).
As a demo, let's start with what OP already has:
orig = readim('https://i.stack.imgur.com/rH7yT.png');
labeled = uint8(round((255-orig{2}(0:866,:))/127));
orange = labeled==1; % for OP this is 3
black = labeled==2; % for OP this is 2 also
(Note that labeled is not identical to the one that OP has, the numbers for each label are different.)
Now we can apply imreconstruct:
black_or_orange = orange | black;
output = imreconstruct(orange,black_or_orange);
output now contains the orange regions, grown to encompass any touching black regions. We can create a new labeled image as follows:
new_labeled = uint8(output) + 2*uint8(black & ~output);

Resize Frame for Optical Flow

I have problem with optical flow if the frame size have been manipulated in any way this gives me error. There are two options either change the resolution of the video at the beginning or somehow how change the frame size in a way that optical flow will work. I will want to add a cascade object to detect nose, mouth and eyes in further development therefore I need solution that will work for individual regions without necessary setting optical flow individually for those regions especially that a bounding box does not have a fixed size and it will displace itself slightly from frame to frame. Here is my code so far, the error is that it is exceeding matrix dimensions.
faceDetector = vision.CascadeObjectDetector();
vidObj = vision.VideoFileReader('MEXTest.mp4','ImageColorSpace','Intensity','VideoOutputDataType','uint8');
converter = vision.ImageDataTypeConverter;
opticalFlow = vision.OpticalFlow('ReferenceFrameDelay', 1);
opticalFlow.OutputValue = 'Horizontal and vertical components in complex form';
shapeInserter = vision.ShapeInserter('Shape','Lines','BorderColor','Custom','CustomBorderColor', 255);
vidPlayer = vision.VideoPlayer('Name','Motion Vector');
while ~isDone(vidObj);
frame = step(vidObj);
fraRes = imresize(frame,0.5);
fbbox = step(faceDetector,fraRes);
I = imcrop(fraRes,fbbox);
im = step(converter,I);
of = step(opticalFlow,im);
lines = videooptflowlines(of, 20);
if ~isempty(lines)
out = step(shapeInserter,im,lines);
step(vidPlayer,out);
end
end
release(vidPlayer);
release(VidObj);
UPDATE: I went and edited the function for optical flow which creates lines and this sorts out the some size issues however it is necessary to to input this manually for each object (so if there is any other way let me know). I think the best solution would be set a fixed size to cascadeObjectDetector, does anyone know how to do this? Or have any other idea?
faceDetector = vision.CascadeObjectDetector(); %I need fixed size for this
faceDetector.MinSize = [150 150];
vidRead = vision.VideoFileReader('MEXTest.mp4','ImageColorSpace','Intensity','VideoOutputDataType','uint8');
convert = vision.ImageDataTypeConverter;
optFlo = vision.OpticalFlow('ReferenceFrameDelay', 1);
optFlo.OutputValue = 'Horizontal and vertical components in complex form';
shapeInserter = vision.ShapeInserter('Shape','Lines','BorderColor','Custom', 'CustomBorderColor', 255);
while ~isDone(vidRead)
frame = step(vidRead);
fraRes = imresize(frame,0.3);
fraSin = im2single(fraRes);
bbox = step(faceDetector,fraSin);
I = imcrop(fraSin, bbox);
im = step(convert, I);
release(optFlo);
of = step(optFlo, im);
lines = optfloo(of, 50); %use videooptflowlines instead of (optfloo)
out = step(shapeInserter, im, lines);
imshow(out);
end

place box on other image in matlab

i have image like:
i want like this
my logic is that make 1st make box. And place that blak box on the picture but failed. any idea that would place black box on this picture????
If you simply need black boxes just set the intensity values of each channel to zero for the area you want. For example:
Image(30:70,100:200,:) = 0;
If you wish it to do it interactively you can use for example roipoly and first obtain a mask:
mask = roipoly(Image)
And then use the mask for each channel:
Image_r = Image(:,:,1);
Image_g = Image(:,:,2);
Image_b = Image(:,:,3);
Image_r(mask) = 0;
Image_g(mask) = 0;
Image_b(mask) = 0;
And reconstruct the original image
Image(:,:,1) = Image_r; Image(:,:,2) = Image_g; Image(:,:,3) = Image_b;
And here you go, beautiful Lena with a hole in the hat.

Annotations on a JFreeChart Pie Chart

Specifically I am looking to add text annotations to specific locations to a JFreeChart that is being output to a png file for web use. Can/how do annotations get added to pie charts. I have been able to successfully add annotations to XYPlots, but don't know how to overlay or add one to a PiePlot.
My full task is to use the PiePlot to create a sort of clock. So far everything has worked great, but now I need to add labels at the 12, 3, 6, and 9 o'clock locations and completely stumped.
Adam
Bit of an old question, but here's how I did something similar (annotation at 1, 2, 3, ... o'clock positions) using a polar plot. It uses a ChoiceFormatter and the NumberTickUnit:
final JFreeChart chart = ChartFactory.createPolarChart(
"HAPI Hourly Usage (UTC)", ds, true, true, false);
final PolarPlot plot = (PolarPlot) chart.getPlot();
// Create a ChoiceFormat to map the degrees to clock positions
double[] limits = new double[12];
String[] formats = new String[12];
limits[0] = 0;
formats[0] = "12";
// degrees = 360/12
for (int i = 1; i < limits.length; i++) {
limits[i] = degrees * (i);
formats[i] = Integer.toString(i);
}
ChoiceFormat clock = new ChoiceFormat(limits, formats);
TickUnit tickUnit = new NumberTickUnit(degrees, clock);
// now configure the plot
plot.setAngleTickUnit(tickUnit); // sets the ticks
plot.setAngleLabelsVisible(true); // makes the labels visible
plot.setAngleLabelPaint(Color.LIGHT_GRAY); // user choice
plot.setAngleGridlinesVisible(true); // must set this to display the
// labels
plot.setAngleGridlinePaint(Color.BLACK); // plot's background color
// (makes lines invisible)
plot.setRadiusGridlinesVisible(false); //turn off the radius value circles
ValueAxis axis = plot.getAxis();
axis.setTickLabelsVisible(false); //turn off the radius value labels
winds up looking like http://img522.imageshack.us/img522/6693/hapihours.jpg
After a fairly strenuous search I don't believe this is currently possible (JFreeChart 1.0.13).
Possible options are:
Create a second chart with an XYPlot to generate a second image with needed annotations. Overlay this image on the page. This option is bad because it doubles the number of chart images to be uploaded.
Set the image as a background on the page and HTML the text over the image. Bad because it isn't maintainable and makes a headache of data transfer.
Personally I am just going to find another way to communicate the information in the title, but I wanted to post my findings for the next person.
Adam