How to keep only a user-defined quantity of labels? - label

First of all sorry for the likely dumb question but i have problems with the label.delete() function used to keep a limited number of labels on charts and deleting older ones, i used this code as reference: https://www.tradingview.com/pine-script-docs/en/v4/concepts/Text_and_shapes.html#deleting-labels
on a function used to create pivots but does not seem to work since it deletes all newer labels created without deleting the older ones, here is the code:
//#version=5
indicator(title='RSI Pivot', precision=0, max_labels_count=500)
qtyLabelsInput = input.int(20, 'Labels to keep', minval=0)
myRSI = ta.rsi(close, 20)
plot(myRSI)
drawLabel(_offset, _pivot, _style, _size, _text, _textcolor) =>
if (_pivot)
label.new(bar_index[_offset], _pivot, style=_style, size=_size, text=_text, textcolor=_textcolor)
if array.size(label.all) > qtyLabelsInput
label.delete(array.get(label.all, 0))
leftLenH = input.int(title='Pivot High main', defval=2, minval=1, inline='Pivot High main')
rightLenH = input.int(title='/', defval=2, minval=1, inline='Pivot High main')
leftLenL = input.int(title='Pivot Low main', defval=2, minval=1, inline='Pivot Low main')
rightLenL = input.int(title='/', defval=2, minval=1, inline='Pivot Low main')
ph = ta.pivothigh(myRSI, leftLenH, rightLenH)
pl = ta.pivotlow(myRSI, leftLenL, rightLenL)
//---------------------------------------------------------------------------------------------------------------MAIN label
drawLabel(rightLenH, ph, label.style_none, size.tiny , "T", color.red)
drawLabel(rightLenL, pl, label.style_none, size.tiny, "B", color.green)
EDIT CODE 2:
//#version=5
indicator(title='CMF Pivot', precision=0, max_labels_count=500)
qtyLabelsInput = input.int(20, 'Labels to keep', minval=0)
myRSI = ta.rsi(close, 20)
plot(myRSI, "RSI")
drawLabel(_offset, _pivot, _style, _size, _text, _textcolor, _y) =>
// x y y(2)=na? plot location
var label[] label_array = array.new_label(qtyLabelsInput)
if (_pivot)
array.unshift(label_array, label.new(bar_index[_offset], _pivot, style=_style, size=_size, text=_text, textcolor=_textcolor, y=_y))
label.delete(array.pop(label_array))
//cmf code
var cumVol = 0.
cumVol += nz(volume)
if barstate.islast and cumVol == 0
runtime.error("No volume is provided by the data vendor.")
length = input.int(20, minval=1)
ad = close==high and close==low or high==low ? 0 : ((2*close-low-high)/(high-low))*volume
cmf = math.sum(ad, length) / math.sum(volume, length)
//
leftLenH = input.int(title='Pivot High main', defval=2, minval=1, inline='Pivot High main')
rightLenH = input.int(title='/', defval=2, minval=1, inline='Pivot High main')
leftLenL = input.int(title='Pivot Low main', defval=2, minval=1, inline='Pivot Low main')
rightLenL = input.int(title='/', defval=2, minval=1, inline='Pivot Low main')
ph = ta.pivothigh(cmf, leftLenH, rightLenH)
pl = ta.pivotlow(cmf, leftLenL, rightLenL)
//---------------------------------------------------------------------------------------------------------------MAIN label
//drawLabel(rightLenH, ph, label.style_none, size.tiny , "T", color.red, myRSI)
//drawLabel(rightLenL, pl, label.style_none, size.tiny, "B", color.green, myRSI)
plotchar(ph, location=location.top, size = size.tiny, text = "H", textcolor = color.red, show_last=15, color=#000000)
plotchar(pl, location=location.bottom, size = size.tiny, text = "L", textcolor = color.green, show_last=15, color=#000000)

You can manage your labels of a fixed number by using a var label array. When your condition is met and you are adding a new label to the array, you also remove and delete the last label in order to keep a fixed number of labels.
drawLabel(_offset, _pivot, _style, _size, _text, _textcolor) =>
var label[] label_array = array.new_label(qtyLabelsInput)
if (_pivot)
array.unshift(label_array, label.new(bar_index[_offset], _pivot, style=_style, size=_size, text=_text, textcolor=_textcolor))
label.delete(array.pop(label_array))

Found the solution, thanks again for your help
drawLabel(_pivot, _y, _style, _size, _text, _textcolor) =>
var label[] label_array = array.new_label(qtyLabelsInput)
if _pivot
array.unshift(label_array, label.new(bar_index[_pivot], y=_y, style=_style, size=_size, text=_text, textcolor=_textcolor))
label.delete(array.pop(label_array))

Related

How to add relevant scale bars on inset maps using tmap

I used tmap to create the plot attached. However, I would like to add a scale bar to the inset map, but I haven't been able to figured out how to do that. Can someone please help me?
Here are the codes that I used to create the attached map:
main_map <- tmap::tm_shape(main_map_df) +
tmap::tm_polygons(
col = "var.q5",
palette = c("#CCCCCC", "#999999", "#666666", "#333333", "#000000"),
#alpha = 0.7,
lwd = 0.5,
title = "") +
tmap::tm_layout(
frame = FALSE,
legend.outside = TRUE,
legend.hist.width = 5,
legend.text.size = 0.5,
fontfamily = "Verdana") +
tmap::tm_scale_bar(
position = c("LEFT", "BOTTOM"),
breaks = c(0, 10, 20),
text.size = 0.5
) +
tmap::tm_compass(position = c("LEFT", "TOP"))
inset_map <- tmap::tm_shape(inset_map_df) +
tmap::tm_polygons() +
tmap::tm_shape(main_map_df) +
tm_fill("grey50") +
tmap::tm_scale_bar(
position = c("LEFT", "BOTTOM"),
breaks = c(0, 10, 20),
text.size = 0.5
)
# Combine crude rate map (inset + main) =====
tiff(
"main_map_w_iset.tiff",
height = 1200,
width = 1100,
compression = "lzw",
res = 300
)
main_map
print(
inset_map,
vp = viewport(
x = 0.7,
y = 0.18,
width = 0.3,
height = 0.3,
clip = "off")
)
dev.off()
Thank you!
Here's a simple example using the World data set:
library(tidyverse)
library(tmap)
library(grid)
data("World")
# main map
tm_main <- World %>%
filter(name == "Australia") %>%
tm_shape() +
tm_polygons(col = "red",
alpha = .5) +
tm_scale_bar()
# inset map
tm_inset <- tm_shape(World) +
tm_polygons(col = "gray",
alpha = .5) +
tm_scale_bar()
vp <- viewport(x = .615, y = .5, width = .6, height = .6, just = c("right", "top"))
# final map
tmap_save(tm_main, filename = "test_inset.png", insets_tm = tm_inset, insets_vp = vp,
height = 200, width = 200, units = "mm")

CAKeyframeAnimation combine animation in scenekit

I'm play around with the CAKeyframeAnimation in order to better understanding how this type of animation work.
I want to move my SCNnode in a square shape and at every corner rotate his eulerangle Y of 90 degrees to make it follow the orientation of the track
here my code
func animatePlaneKey(nodeToAnimate: SCNNode){
// move forward
let pos = nodeToAnimate.position
let animation = CAKeyframeAnimation(keyPath: "position")
let pos1 = SCNVector3(pos.x, pos.y, pos.z)
let pos2 = SCNVector3(pos.x + 1 , pos.y, pos.z)
let pos3 = SCNVector3(pos.x + 1 , pos.y, pos.z + 1) // 1
let pos4 = SCNVector3(pos.x - 1 , pos.y, pos.z + 1)
let pos5 = SCNVector3(pos.x, pos.y, pos.z)
let easeIn = CAMediaTimingFunction(controlPoints: 0.35, 0.0, 1.0, 1.0)
animation.values = [pos1,pos2, pos3,pos4,pos5]
animation.keyTimes = [0,0.25,0.5,0.75,1]
animation.timingFunctions = [easeIn]
animation.calculationMode = .cubic
animation.duration = 12
animation.repeatCount = 1
animation.isAdditive = false
animation.autoreverses = false
// Heading 1st
let firstTurnAnim = CAKeyframeAnimation(keyPath: "eulerAngles.y")
let heading = nodeToAnimate.eulerAngles.y
let rot0heading = heading
let rot2heading = heading - Float(deg2rad(90))
firstTurnAnim.values = [rot0heading,rot2heading]
firstTurnAnim.keyTimes = [0.2,0.3]
firstTurnAnim.duration = 3
firstTurnAnim.repeatCount = 1
firstTurnAnim.isAdditive = true
firstTurnAnim.autoreverses = false
// // Heading 2st
let secondTurnAnim = CAKeyframeAnimation(keyPath: "eulerAngles.y")
let heading2 = nodeToAnimate.eulerAngles.y
let rot1head0 = heading2
let rot1head1 = heading2 - Float(deg2rad(180))
secondTurnAnim.values = [rot1head0,rot1head1]
secondTurnAnim.keyTimes = [0.45,0.55]
secondTurnAnim.duration = 6
secondTurnAnim.repeatCount = 1
secondTurnAnim.isAdditive = true
secondTurnAnim.autoreverses = false
nodeToAnimate.addAnimation(animation, forKey: "movement")
nodeToAnimate.addAnimation(firstTurnAnim, forKey: "turn")
nodeToAnimate.addAnimation(secondTurnAnim, forKey: "turn2")
}
I'm struggling to combine the animation of the y axis at the correct time.
when I add the "turn2" the animation start to mess up everything's, the node appear already rotate in the wrong direction.
For my understanding turn2 animation should start at keyframe 0.45 and finish at 0.55, why it start immediately ?
any idea what should be the correct way to combine this animation?

How can I display a quiver plot between two cross-correlated images?

I have written a code in MATLAB which allows me to automatically crop regions of interest in one image, and perform cross-correlation with a second image. The correlated regions are identified by a quiver plot, which I would like to extend across the two images (they are arranged in a vertical montage). However, the quiver arrows appear only in the upper image.
Would anyone know why this happens (and how to fix it)? Hopefully it's something straightforward. I've included some of my code below. Thanks!
Initial = rgb2gray(imread('img9.png'));
Secondary = rgb2gray(imread('img8.png'));
XC = imcrop(Initial, [0 0 1300 350]);
YC = imcrop(Secondary, [0 0 1300 350]);
Multi = cat(1,XC,YC);
VertLinSpace1 = linspace(0, 300, 7);
HorzLinSpace1 = linspace(0, 1250, 24);
imshow(Multi)
axis( [0 1300 0 700])
axis on
for k1 = 1:length(VertLinSpace1)
for k2 = 1:length(HorzLinSpace1)
template = imcrop(Multi, [HorzLinSpace1(k2) VertLinSpace1(k1), 50 50]);
c = normxcorr2(template,YC);
[ypeak, xpeak] = find(c==max(c(:)));
yO = ypeak-size(template,1);
xO = xpeak-size(template,2);
x1 = HorzLinSpace1(k2); y1 = VertLinSpace1(k1); x2 = xO+1; y2 = yO+1;
a = [x1, y1, 0];
b = [x2, y2, 0];
Q = [x1 y1
x2 y2];
QX = Q(:,1);
QY = Q(:,2);
[~,UV] = gradient(Q);
UVX = [UV(1,1); 0];
UVY = [UV(1,2); 0];
figure(1)
hold on
quiver(QX, QY, UVX, UVY, 'color','red')
hold off
end
end
Initial image
Comparison image
I simplified the arrow XY computation, but the essence was to add 350 to point down to the second half. I added 25 to indicate the middle of the template (the tail of the arrows). This may not be 100% accurate solution, because, for example, the middle of a 50 by 50 pixel square is 25.5 (25 pixels on either side) but it solves the main issue and you can take it from here.
Initial = rgb2gray(imread('https://i.stack.imgur.com/5fTa1.png'));
Secondary = rgb2gray(imread(('https://i.stack.imgur.com/sg1co.png')));
XC = imcrop(Initial, [0 0 1300 350]);
YC = imcrop(Secondary, [0 0 1300 350]);
Multi = cat(1,XC,YC);
VertLinSpace1 = linspace(0, 300, 7);
HorzLinSpace1 = linspace(0, 1250, 24);
imshow(Multi)
axis( [0 1300 0 700])
axis on
hold on
counter = 0;
for kV = 1:length(VertLinSpace1)
for kH = 1:length(HorzLinSpace1)
template = imcrop(Multi, [HorzLinSpace1(kH) VertLinSpace1(kV), 50 50]);
c = normxcorr2(template,YC);
[ypeak, xpeak] = find(c==max(c(:)));
fromXY = [HorzLinSpace1(kH)+25,VertLinSpace1(kV)+25];
addXY = [xpeak-fromXY(1),350+ypeak-fromXY(2)];
quiver(fromXY(1), fromXY(2), addXY(1), addXY(2), 'color','red')
drawnow
end
end

LPR with MATLAB: how to find only one rectangle?

I am using the following code in MATLAB to find the rectangle containing a car's license plate:
clc
clear
close all
%Open Image
I = imread('plate_1.jpg');
figure, imshow(I);
%Gray Image
Ib = rgb2gray(I);
figure,
subplot(1,2,1), imshow(Ib);
%Enhancement
Ih = histeq(Ib);
subplot(1,2,2), imshow(Ih);
figure,
subplot(1,2,1), imhist(Ib);
subplot(1,2,2), imhist(Ih);
%Edge Detection
Ie = edge(Ih, 'sobel');
figure,
subplot(1,2,1), imshow(Ie);
%Dilation
Id = imdilate(Ie, strel('diamond', 1));
subplot(1,2,2), imshow(Id);
%Fill
If = imfill(Id, 'holes');
figure, imshow(If);
%Find Plate
[lab, n] = bwlabel(If);
regions = regionprops(lab, 'All');
regionsCount = size(regions, 1) ;
for i = 1:regionsCount
region = regions(i);
RectangleOfChoice = region.BoundingBox;
PlateExtent = region.Extent;
PlateStartX = fix(RectangleOfChoice(1));
PlateStartY = fix(RectangleOfChoice(2));
PlateWidth = fix(RectangleOfChoice(3));
PlateHeight = fix(RectangleOfChoice(4));
if PlateWidth >= PlateHeight*3 && PlateExtent >= 0.7
im2 = imcrop(I, RectangleOfChoice);
figure, imshow(im2);
end
end
Plates all have white backgrounds. Currently,I use the rectangles' ratio of width to height to select candidate regions for output. This gives the plate rectangle in addition to several other irrelevant ones in the case of a white car. What method can I use to get only one output: the license plate?
Also, I don't find a plate at all when I run the code on a black car. Maybe that's because the car's color is the same as the plate edge.
Are there any alternatives to edge detection to avoid this problem?
Try this !!!
I = imread('http://8pic.ir/images/88146564605446812704.jpg');
im=rgb2gray(I);
sigma=1;
f=zeros(128,128);
f(32:96,32:96)=255;
[g3, t3]=edge(im, 'canny', [0.04 0.10], sigma);
se=strel('rectangle', [1 1]);
BWimage=imerode(g3,se);
gg = imclearborder(BWimage,8);
bw = bwareaopen(gg,200);
gg1 = imclearborder(bw,26);
imshow(gg1);
%Dilation
Id = imdilate(gg1, strel('diamond', 1));
imshow(Id);
%Fill
If = imfill(Id, 'holes');
imshow(If);
%Find Plate
[lab, n] = bwlabel(If);
regions = regionprops(lab, 'All');
regionsCount = size(regions, 1) ;
for i = 1:regionsCount
region = regions(i);
RectangleOfChoice = region.BoundingBox;
PlateExtent = region.Extent;
PlateStartX = fix(RectangleOfChoice(1));
PlateStartY = fix(RectangleOfChoice(2));
PlateWidth = fix(RectangleOfChoice(3));
PlateHeight = fix(RectangleOfChoice(4));
if PlateWidth >= PlateHeight*1 && PlateExtent >= 0.7
im2 = imcrop(I, RectangleOfChoice);
%figure, imshow(I);
figure, imshow(im2);
end
end

Adding an image to an animation in matlab

I created a 3D stick man walking in matlab and I want to add an image as the floor that he is walking on. I'm not sure how to go about doing this. I looked at an example of someone adding an image as a background. That is kinda what I want but I want it to appear as the floor. I going to give the stick man a trajectory and make him walk across the floor. Can anyone point me in the right direction.
Ok now I got it thanks to Andrey.
clear all
cyl = UnitCylinder(2);
sph = UnitSphere(2);
% Head
L1 = 2;
Head = translate(scale(sph,L1/2, L1/2, L1/2),0,0,L1+4.5);
Head.facecolor = 'yellow';
%Shoulder
r2 = 0.3;
L2 = 3;
Shoulder = translate(rotateX(scale(cyl,r2/2,r2/2,L2/2),90),0,0,5);
Shoulder.facecolor = 'red';
%Left Upper Arm
w1_s = [-20:4:20 20:-4:-20];
r3 = 0.3;
L3 = 2;
Upper_Arm_left = translate(scale(cyl,r3/2,r3/2,L3/2),0,0,-L3/2);
Upper_Arm_left.facecolor = 'red';
%Right Upper Arm
Upper_Arm_right = translate(scale(cyl,r3/2,r3/2,L3/2),0,0,-L3/2);
Upper_Arm_right.facecolor = 'red';
%Left Forearm
w2_s = [-5:1:5 5:-1:-5];
L3_f = 2.5;
Fore_Arm_left = translate(scale(cyl,r3/2,r3/2,L3_f/2),0,0,-L3_f/2);
Fore_Arm_left.facecolor = 'red';
%Right Forearm
Fore_Arm_right = translate(scale(cyl,r3/2,r3/2,L3_f/2),0,0,-L3_f/2);
Fore_Arm_right.facecolor = 'red';
%Chest
r4 = 2;
L4 = 2;
Chest = translate(scale(cyl,r4/2,r4/2,L4/2),0, 0, 5-L4/2);
Chest.facecolor = 'yellow';
%Weist
r5 = 1;
L5 = 2;
Weist = translate(scale(cyl,r5/2,r5/2,L5/2),0, 0, 5-L4-L5/2);
Weist.facecolor = 'yellow';
%Hip
L6 = 1.5;
Hip = translate(rotateX(scale(cyl,r2/2,r2/2,L6/2),90),0,0,5-L4-L5-r2/2);
Hip.facecolor = 'green';
%Left Upper Leg
r7 = 0.4;
L7 = 2.5;
L71 = (L6/2+r7/2);
L72 = 5-L7/2-L4-L5;
Upper_Leg_left = translate(scale(cyl,r7/2,r7/2,L7/2),0,0,-L7/2);
Upper_Leg_left.facecolor = 'green';
%Right Upper Leg
Upper_Leg_right = translate(scale(cyl,r7/2,r7/2,L7/2),0,0,-L7/2);
Upper_Leg_right.facecolor = 'green';
%Left Lower Leg
L7_f = 3;
Lower_Leg_left = translate(scale(cyl,r7/2,r7/2,L7_f/2),0,0,-L7_f/2);
Lower_Leg_left.facecolor = 'green';
%Right Lower Leg
Lower_Leg_right = translate(scale(cyl,r7/2,r7/2,L7_f/2),0,0,-L7_f/2);
Lower_Leg_right.facecolor = 'green';
angle1 = 0;
angle2 = 0;
for i = 1:120
angle1 = w1_s(rem(i,length(w1_s))+1);
angle2 = w2_s(rem(i,length(w1_s))+1);
Arm_left = combine(translate(rotateY(Fore_Arm_left,angle2),0,0,-L3), Upper_Arm_left);
Arm_right = combine(translate(rotateY(Fore_Arm_right,-angle2),0,0,-L3), Upper_Arm_right);
Arm_left = translate(rotateY(Arm_left,angle1),0,-L2/2,(5-L3/2)+L3/2);
Arm_right = translate(rotateY(Arm_right,-angle1),0,L2/2,(5-L3/2)+L3/2);
Leg_left = combine(translate(rotateY(Lower_Leg_left,-angle2),0,0,-L7), Upper_Leg_left);
Leg_right = combine(translate(rotateY(Lower_Leg_right,angle2),0,0,-L7), Upper_Leg_right);
Leg_left = translate(rotateY(Leg_left,-angle1),0,-L71,L72+L7/2);
Leg_right = translate(rotateY(Leg_right,angle1),0,L71,L72+L7/2);
Upper_Body = combine(Head, Shoulder, Arm_left, Arm_right, Chest, Weist);
Lower_Body = combine(Hip, Leg_left, Leg_right);
walker = combine(Upper_Body, Lower_Body);
cla
img = imread('peppers.png');
[X,Y] = ndgrid([-10 10],[-10 10]);
zImage = [-5 -5; -5 -5];
surf(X,Y,zImage,'CData',img,'FaceColor','texturemap');
% view([1 1 1]);
hold on
view(3)
set(gca,'xlim',[-10 10],'ylim',[-10 10],'zlim',[-6 6]);
renderpatch(walker);
camlight
box on
drawnow
pause(0.04)
end
I want to get something like this floor but I don't know how to do it. This person used a .fig in their code.This is a piece of what they used.
F1 = open('background1.fig');
background_gca = gca;
F2 = figure(2);
.
.
.
clf(F2)
copyobj(background_gca,F2);
view([-40,25])
set(gca,'xlim',[-5 5],'ylim',[-5 5],'zlim',[0 10]);
renderpatch(walker);
camlight
box on
% axis off
drawnow;
You had a small syntax error:
First, you reversed z and y :
surf(xImage,zImage,yImage,...)
Also, you should think about surf as a surface. Thus, all z should be 0
img = imread('peppers.png');
[X,Y] = ndgrid([-5 5],[-5 5]);
zImage = [0 0; 0 0];
surf(X,Y,zImage,'CData',img,'FaceColor','texturemap');
view([1 1 1]);
make that background image as GIF image, it feels like man walking on floor
otherwise visit here, useful video:http://www.youtube.com/watch?v=Ztb6_kIkXb8

Resources