How to calculate anchor boxes given scale and ratio? - object-detection-api

I am referring to code from this Git repository: https://github.com/kbardool/Keras-frcnn/ I don't understand the below code.
# anchor box scales
self.anchor_box_scales or anchor_size = [128, 256, 512]
# anchor box ratios
self.anchor_box_ratios = [[1, 1], [1./math.sqrt(2), 2./math.sqrt(2)], [2./math.sqrt(2), 1./math.sqrt(2)]]
how x1_anc,x2_anc and y1_anc,y2_anc calculated
for anchor_size_idx in range(len(anchor_sizes)):
for anchor_ratio_idx in range(n_anchratios):
anchor_x = anchor_sizes[anchor_size_idx] * anchor_ratios[anchor_ratio_idx][0]
anchor_y = anchor_sizes[anchor_size_idx] * anchor_ratios[anchor_ratio_idx][1]
for ix in range(output_width):
# x-coordinates of the current anchor box
x1_anc = int(downscale * (ix + 0.5) - anchor_x / 2)
x2_anc = int(downscale * (ix + 0.5) + anchor_x / 2)
# ignore boxes that go across image boundaries
if x1_anc < 0 or x2_anc > resized_width:
continue
for jy in range(output_height):
# y-coordinates of the current anchor box
y1_anc = int(downscale * (jy + 0.5) - anchor_y / 2)
y2_anc = int(downscale * (jy + 0.5) + anchor_y / 2)
# ignore boxes that go across image boundaries
if y1_anc < 0 or y2_anc > resized_height:
continue

Related

How to set parameters for Conv

I am modifying YOLOV5 into a rotating object detection network and replacing its head part with a decoupled head. I successfully replaced the head of the origin YOLOV5 with a decoupled head, but when I tried to replace it for my modified YOLOV5, it reported an error :RuntimeError: Given groups=1, weight of size [256, 128, 1, 1], expected input[1, 63, 32, 32] to have 128 channels,
but got 63 channels instead. The only part I changed in the head of YOLOV5 is that I turned self.no = nc + 5 into self.no = nc + 5 + 180, to adapt to rotating target detection scenarios.
This is the modification I made for the decoupled head
class DecoupledHead(nn.Module):
def __init__(self, ch=256, nc=80, width=1.0, anchors=()):
super().__init__()
self.nc = nc # number of classes
self.nl = len(anchors) # number of detection layers
self.na = len(anchors[0]) // 2 # number of anchors
self.merge = Conv(ch, 256 * width, 1, 1)
self.cls_convs1 = Conv(256 * width, 256 * width, 3, 1, 1)
self.cls_convs2 = Conv(256 * width, 256 * width, 3, 1, 1)
self.reg_convs1 = Conv(256 * width, 256 * width, 3, 1, 1)
self.reg_convs2 = Conv(256 * width, 256 * width, 3, 1, 1)
self.cls_preds = nn.Conv2d(256 * width, self.nc * self.na, 1)
self.reg_preds = nn.Conv2d(256 * width, 4 * self.na, 1)
self.obj_preds = nn.Conv2d(256 * width, 1 * self.na, 1)
def forward(self, x):
x = self.merge(x)
x1 = self.cls_convs1(x)
x1 = self.cls_convs2(x1)
x1 = self.cls_preds(x1)
x2 = self.reg_convs1(x)
x2 = self.reg_convs2(x2)
x21 = self.reg_preds(x2)
x22 = self.obj_preds(x2)
out = torch.cat([x21, x22, x1], 1)
return out
and I changed __init__ in class Detect with
def __init__(self, nc=80, anchors=(), ch=(), inplace=True): # detection layer
super().__init__()
self.n_anchors = 1
self.nc = nc # number of classes
self.no = nc + 5 + 180 # number of outputs per anchor
self.nl = len(anchors) # number of detection layers
self.na = len(anchors[0]) // 2 # number of anchors
self.grid = [torch.zeros(1)] * self.nl # init grid
self.anchor_grid = [torch.zeros(1)] * self.nl # init anchor grid
self.register_buffer('anchors', torch.tensor(anchors).float().view(self.nl, -1, 2)) # shape(nl,na,2)
# self.m = nn.ModuleList(nn.Conv2d(x, self.no * self.na, 1) for x in ch) # output conv
self.m = nn.ModuleList(DecoupledHead(x, nc, 1, anchors) for x in ch)
self.inplace = inplace # use in-place ops (e.g. slice assignment)
The origin __init__ was like
def __init__(self, nc=80, anchors=(), ch=(), inplace=True): # detection layer
super().__init__()
self.n_anchors = 1
self.nc = nc # number of classes
self.no = nc + 5 # number of outputs per anchor
self.nl = len(anchors) # number of detection layers
self.na = len(anchors[0]) // 2 # number of anchors
self.grid = [torch.zeros(1)] * self.nl # init grid
self.anchor_grid = [torch.zeros(1)] * self.nl # init anchor grid
self.register_buffer('anchors', torch.tensor(anchors).float().view(self.nl, -1, 2)) # shape(nl,na,2)
self.m = nn.ModuleList(nn.Conv2d(x, self.no * self.na, 1) for x in ch) # output conv
self.inplace = inplace # use in-place ops (e.g. slice assignment)
How to modify the class DecoupledHead to make it work?

Snake Game score not adding

This snake game code. I want to add the system score in this game. So that each time the snake eating his score would be increased. But if the snake does not get food score will not increase.
How do I go about displaying the current score?
this is :
""" A simple snake game using Turtle Graphics. """
import turtle
import math
import random
WIDTH = 500
HEIGHT = 500
FOOD_SIZE = 10
DELAY = 100 # milliseconds
offsets = {
"up": (0, 20),
"down": (0, -20),
"left": (-20, 0),
"right": (20, 0)
}
scores are not updating
def addscore():
global score
score += 1
def reset():
global snake, snake_direction, food_pos, pen
snake = [[0, 0], [0, 20], [0, 40], [0, 60], [0, 80]]
snake_direction = "up"
food_pos = get_random_food_pos()
food.goto(food_pos)
#screen.update() Only needed if we are fussed about drawing food before next call to `draw_snake()`.
move_snake()
def move_snake():
global snake_direction
# Next position for head of snake.
new_head = snake[-1].copy()
new_head[0] = snake[-1][0] + offsets[snake_direction][0]
new_head[1] = snake[-1][1] + offsets[snake_direction][1]
# Check self-collision
if new_head in snake[:-1]: # Or collision with walls?
reset()
else:
# No self-collision so we can continue moving the snake.
snake.append(new_head)
# Check food collision
if not food_collision():
snake.pop(0) # Keep the snake the same length unless fed.
wrapping up
# Allow screen wrapping
if snake[-1][0] > WIDTH / 2:
snake[-1][0] -= WIDTH
elif snake[-1][0] < - WIDTH / 2:
snake[-1][0] += WIDTH
elif snake[-1][1] > HEIGHT / 2:
snake[-1][1] -= HEIGHT
elif snake[-1][1] < -HEIGHT / 2:
snake[-1][1] += HEIGHT
# Clear previous snake stamps
pen.clearstamps()
# Draw snake
for segment in snake:
pen.goto(segment[0], segment[1])
pen.stamp()
# Refresh screen
screen.update()
# Rinse and repeat
turtle.ontimer(move_snake, DELAY)
def food_collision():
global food_pos
if get_distance(snake[-1], food_pos) < 20:
food_pos = get_random_food_pos()
food.goto(food_pos)
return True
return False
def get_random_food_pos():
x = random.randint(- WIDTH / 2 + FOOD_SIZE, WIDTH / 2 - FOOD_SIZE)
y = random.randint(- HEIGHT / 2 + FOOD_SIZE, HEIGHT / 2 - FOOD_SIZE)
return (x, y)
def get_distance(pos1, pos2):
x1, y1 = pos1
x2, y2 = pos2
distance = ((y2 - y1) * 2 + (x2 - x1) * 2) ** 0.5
return distance
def go_up():
global snake_direction
if snake_direction != "down":
snake_direction = "up"
def go_right():
global snake_direction
if snake_direction != "left":
snake_direction = "right"
def go_down():
global snake_direction
if snake_direction != "up":
snake_direction = "down"
def go_left():
global snake_direction
if snake_direction != "right":
snake_direction = "left"
# Screen
screen = turtle.Screen()
screen.setup(WIDTH, HEIGHT)
screen.title("Snake")
screen.bgcolor("green")
screen.setup(500, 500)
screen.tracer(0)
# Pen
pen = turtle.Turtle("square")
pen.penup()
pen.hideturtle()
pen.goto(0, 250)
pen.write("Score : 0 High Score : 0", align="center", font=("candara", 24, "bold"))
# Food
food = turtle.Turtle()
food.shape("circle")
food.color("red")
food.shapesize(FOOD_SIZE / 20) # Default size of turtle "square" shape is 20.
food.penup()
# Event handlers
screen.listen()
screen.onkey(go_up, "Up")
screen.onkey(go_right, "Right")
screen.onkey(go_down, "Down")
screen.onkey(go_left, "Left")
# Let's go
reset()
turtle.done()
It's defined, but you have to call your addscore() function. Replace
if not food_collision():
snake.pop(0)
with
if food_collision():
addscore()
else:
snake.pop(0)
You can just add this code to your game. It will write a score:
score = 0
#Creating Score Writer
turtle.hideturtle()
turtle.penup()
turtle.color("white")
turtle.goto(-300,300)
turtle.write(f"Score = {score}", font=("Arial",16,"normal"))
You also don't need a screen.setup() for this.
You can change the score variable. Every time you want the text to update you write
turtle.clear()
turtle.write(f"Score = {score}", font=("Arial",16,"normal"))

I am trying to implement the Harris corner detection algorithm from scratch, but could not able to implement the non-maximum suppression

I am trying to implement Harris corner detection algorithm from the scratch. The output of this algorithm should supposed to get one single pixel representing the corner, but in my code I am getting multiple pixel representing the corner. This is may be because of not implemented the final part of the algorithm that is non-maximum suppression. This I could not able to implement because I did not understand it properly. How to implement this? Along with this I am also trying to find the coordinates of these corner, how to do this with out using cv2 library?
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as im
# 1. Before doing any operations convert the image into gray scale image
img = im.imread('OD6.jpg')
plt.imshow(img)
plt.show()
# split
R=img[:,:,0]
G=img[:,:,1]
B=img[:,:,2]
M,N=R.shape
gray_img=np.zeros((M,N), dtype=int);
for i in range(M):
for j in range(N):
gray_img[i, j]=(R[i, j]*0.2989)+(G[i, j]*0.5870)+(B[i, j]*0.114);
plt.imshow(gray_img, cmap='gray')
plt.show()
# 2. Applying sobel filter to get the gradients of the images in x and y directions
sobelx = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]], dtype = np.float)
sobely = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]], dtype = np.float)
sobelxImage = np.zeros((M,N))
sobelyImage = np.zeros((M,N))
sobelGrad = np.zeros((M,N))
image = np.pad(gray_img, (1,1), 'edge')
for i in range(1, M-1):
for j in range(1, N-1):
gx = (sobelx[0][0] * image[i-1][j-1]) + (sobelx[0][1] * image[i-1][j]) + \
(sobelx[0][2] * image[i-1][j+1]) + (sobelx[1][0] * image[i][j-1]) + \
(sobelx[1][1] * image[i][j]) + (sobelx[1][2] * image[i][j+1]) + \
(sobelx[2][0] * image[i+1][j-1]) + (sobelx[2][1] * image[i+1][j]) + \
(sobelx[2][2] * image[i+1][j+1])
gy = (sobely[0][0] * image[i-1][j-1]) + (sobely[0][1] * image[i-1][j]) + \
(sobely[0][2] * image[i-1][j+1]) + (sobely[1][0] * image[i][j-1]) + \
(sobely[1][1] * image[i][j]) + (sobely[1][2] * image[i][j+1]) + \
(sobely[2][0] * image[i+1][j-1]) + (sobely[2][1] * image[i+1][j]) + \
(sobely[2][2] * image[i+1][j+1])
sobelxImage[i-1][j-1] = gx
sobelyImage[i-1][j-1] = gy
g = np.sqrt(gx * gx + gy * gy)
sobelGrad[i-1][j-1] = g
sobelxyImage = np.multiply(sobelxImage, sobelyImage)
# 3 Apply gaussian filter along x y and xy
size=3;# define the filter size
sigma=1; # define the standard deviation
size = int(size) // 2
xx, yy = np.mgrid[-size:size+1, -size:size+1]
normal = 1 / (2.0 * np.pi * sigma**2)
gg = np.exp(-((xx**2 + yy**2) / (2.0*sigma**2))) * normal
gaussx =gg
gaussy =gg
gaussxImage = np.zeros((M,N))
gaussyImage = np.zeros((M,N))
gaussxyImage = np.zeros((M,N))
gaussresult = np.zeros((M,N))
gaussimagex = np.pad(sobelxImage, (1,1), 'edge')
gaussimagey = np.pad(sobelyImage, (1,1), 'edge')
gaussimagexy = np.pad(sobelxyImage, (1,1), 'edge')
for i in range(1, M-1):
for j in range(1, N-1):
ggx = (gaussx[0][0] * gaussimagex[i-1][j-1]) + (gaussx[0][1] *gaussimagex[i-1][j]) + \
(gaussx[0][2] * gaussimagex[i-1][j+1]) + (gaussx[1][0] * gaussimagex[i][j-1]) + \
(gaussx[1][1] * gaussimagex[i][j]) + (gaussx[1][2] * gaussimagex[i][j+1]) + \
(gaussx[2][0] * gaussimagex[i+1][j-1]) + (gaussx[2][1] * gaussimagex[i+1][j]) + \
(gaussx[2][2] * gaussimagex[i+1][j+1])
ggy = (gaussy[0][0] * gaussimagey[i-1][j-1]) + (gaussy[0][1] * gaussimagey[i-1][j]) + \
(gaussy[0][2] * gaussimagey[i-1][j+1]) + (gaussy[1][0] * gaussimagey[i][j-1]) + \
(gaussy[1][1] * gaussimagey[i][j]) + (gaussy[1][2] * gaussimagey[i][j+1]) + \
(gaussy[2][0] * gaussimagey[i+1][j-1]) + (gaussy[2][1] * gaussimagey[i+1][j]) + \
(gaussy[2][2] * gaussimagey[i+1][j+1])
crossgg = (gg[0][0] * gaussimagexy[i-1][j-1]) + (gg[0][1] * gaussimagexy[i-1][j]) + \
(gg[0][2] * gaussimagexy[i-1][j+1]) + (gg[1][0] * gaussimagexy[i][j-1]) + \
(gg[1][1] * gaussimagexy[i][j]) + (gg[1][2] * gaussimagexy[i][j+1]) + \
(gg[2][0] * gaussimagexy[i+1][j-1]) + (gg[2][1] * gaussimagexy[i+1][j]) + \
(gg[2][2] * gaussimagexy[i+1][j+1])
gaussxImage[i-1][j-1] = ggx
gaussyImage[i-1][j-1] = ggy
gaussxyImage[i-1][j-1] = crossgg
blur = np.sqrt(ggx * ggx + ggy * ggy)
gaussresult[i-1][j-1] = blur
det = gaussxImage *gaussyImage - (gaussxyImage ** 2)
alpha = 0.04
trace = alpha * (gaussxImage +gaussyImage) ** 2
#finding the harris response
R = det - trace
# applying threshold
for i in range(1, M-1):
for j in range(1, N-1):
if R[i][j] > 140:
R[i][j]==0
else:
R[i][j]==255
f, ax1 = plt.subplots(1, 1, figsize=(5,5))
ax1.set_title('corners')
ax1.imshow(R, cmap="gray")
First of all, there are a couple of bugs in your code:
The R[i][j]==0 part in the final thresholding loop should be R[i][j]=0. Note thought that you don't have to go through a loop, you can just do something like R[R>thresh]=255 etc.
If I'm not mistaken, the R values that corresponds to corners in Harris' algorithm are the large positive ones. When I run your code, I get R values that are negative for edges and corners, so I suspect that there is a bug somewhere there.
At this point, I don't think that the main issue in your code is non-maxima suppression, but in case it still is, here is a quick explanation of non maxima suppression and the paper that we discussed in the comments:
Basically, the idea of non-maximal suppression is very simple: if the (corner) response of a point x is not the highest in a neighborhood (that you are free to define depending on your needs), then you don't keep it. In your case, it will probably be simply sufficient to compare the response of each of your detected interest points with the response of its closest neighbors and keep them only if they are higher with respect to all of them. As for the paper that we discussed, its aim is to suppress keypoints (that are not local maxima) in a way that results in a more uniform spatial distribution. Let S be the keypoints lits, sorted in decreasing order of corner response. The idea is to assign each of them to a "suppression radius", that is, a radius in which those points wont be considered a local maximum. As S[0] has the highest corner response in the image, it will never be suppressed, so you can set its radius of suppression radius_list[0]=inf. Next, let's look at S[1]. As the list S is sorted, the only point with highest response than S[1] is S[0], and from that, it follows that the radius at which S[1] stops being a local maximum is Dist(S[1], S[2]). That is, once we include S[0] in the local neighborhood of S[1], since response[S[0]]>response[S[1]], S[0] will become the maximum in that neighborhood. Note that as you continue like this, the radii that you consider will become smaller and smaller. Once you have computed radius_list, assuming you need N feature points, you will just select the N points that have the highest radius_list values. In pseudo-code:
#let S be the keypoints, sorted in decreasing corner response order
#Assume you want only to keep N keypoints at the end
radius=zeros(len(S))
radius[0]=inf
for i in range(len(S[1:])):
candidate_radii=[]
for j in range(0,i):
if response[i]<response[j]*some_const:#you can set some_const to something in [0.9,1]
candidate_radii.append(image_space_dist(S[i],S[j]))
radius[i]=min(candidate_radii)
sorted_indexes = argsort(radius)
kept_points = S[sorted_indexes][:N]
Hope this helps.

OpenCV bilinear downsampling with non-integer scaling

I need help in figuring out the algorithm/implementation OpenCV is using for image-downsampling with non-linear scaling factors.
I know the question was already ask a few times, but most answers seem to not match OpenCV's implementation (for instance, this answer is not correct when using OpenCV: https://math.stackexchange.com/questions/48903/2d-array-downsampling-and-upsampling-using-bilinear-interpolation).
Minimal problem formulation:
I want to downsample an image of resolution 4x4 to an image of resolution 3x3 using bilinear interpolation. I am interested in the interpolation coefficients.
Example in python:
img = np.asarray([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[13, 14, 15, 16]]).astype(np.float32)
img_resized = cv2.resize(img, (3, 3), 0, 0, cv2.INTER_LINEAR).astype(np.float32)
print(img)
# [[ 1. 2. 3. 4.]
# [ 5. 6. 7. 8.]
# [ 9. 10. 11. 12.]
# [13. 14. 15. 16.]]
print(img_resized)
# [[ 1.8333333 3.1666667 4.5 ]
# [ 7.166667 8.5 9.833333 ]
# [12.5 13.833333 15.166666 ]]
Interpolation coefficients:
After a lot of trial-and-error, I figured out the interpolation coefficients OpenCV is using for this specific case.
For the corner points of the 3x3 image:
1.8333333 = 25/36 * 1 + 5/36 * 2 + 5/36 * 5 + 1/36 * 6
4.5000000 = 25/36 * 4 + 5/36 * 3 + 5/36 * 8 + 1/36 * 7
12.5000000 = 25/36 * 13 + 5/36 * 9 + 5/36 * 14 + 1/36 * 10
15.1666666 = 25/36 * 16 + 5/36 * 15 + 5/36 * 12 + 1/36 * 11
For the middle points of the 3x3 image:
8.5 = 1/4 * 6 + 1/4 * 7 + 1/4 * 10 + 1/4 * 11
For the remaining 4 points of the 3x3 image:
3.1666667 = 5/12 * 2 + 5/12 * 3 + 1/12 * 6 + 1/12 * 7
7.1666667 = 5/12 * 5 + 5/12 * 9 + 1/12 * 6 + 1/12 * 10
9.8333333 = 5/12 * 8 + 5/12 * 12 + 1/12 * 7 + 1/12 * 11
13.833333 = 5/12 * 14 + 5/12 * 15 + 1/12 * 10 + 1/12 * 11
Question:
Can someone please help me make sense of these interpolation coefficients? How are they calculated? I tried to read the source of the cv::resize() function, but it did not help me a lot :S
After playing around with various test cases, I think I know the answer to how OpenCV chooses the sample point locations. As #ChrisLuengo has pointed out in a comment, OpenCV seems to not apply a low-pass filter before downsampling, but uses (bi-)linear interpolation only.
(Possible) Solution:
Let's assume we have a 5x5 image, which pixel positions are represented with the blue circles in the graphic below. We now want to downsample it to a 3x3, or a 4x4 image, and need to find the sample positions of the new downsampled image in the original image grid.
It appears to be that OpenCV uses pixel distance of 1 for the original image grid, and a pixel distance of (OLD_SIZE / NEW_SIZE), thus here 5/3 and 5/4, for the new image grid. Moreover, it aligns both grids at the center point. Thus, OpenCV's deterministic sampling algorithms can be visualized as follows:
Visualization 5x5 to 3x3:
Visualization 5x5 to 4x4:
Sample Code (Python 2.7):
import numpy as np
import cv2
# 1. H_W is the height & width of the original image, using uniform H/W for this example
# resized_H_W is the height & width of the resized image, using uniform H/W for this example
H_W = 5
resized_H_W = 4
# 2. Create original image & Get OpenCV resized image:
img = np.zeros((H_W, H_W)).astype(np.float32)
counter = 1
for i in range(0, H_W):
for j in range(0, H_W):
img[i, j] = counter
counter += 1
img_resized_opencv = cv2.resize(img, (resized_H_W, resized_H_W), 0, 0, cv2.INTER_LINEAR).astype(np.float32)
# 3. Get own resized image:
img_resized_own = np.zeros((resized_H_W, resized_H_W)).astype(np.float32)
for i in range(0, resized_H_W):
for j in range(0, resized_H_W):
sample_x = (1.0 * H_W) / 2.0 - 0.50 + (i - (1.0 * resized_H_W - 1.0) / 2.0) * (1.0 * H_W) / (1.0 * resized_H_W)
sample_y = (1.0 * H_W) / 2.0 - 0.50 + (j - (1.0 * resized_H_W - 1.0) / 2.0) * (1.0 * H_W) / (1.0 * resized_H_W)
pixel_top_left = img[int(np.floor(sample_x)), int(np.floor(sample_y))]
pixel_top_right = img[int(np.floor(sample_x)), int(np.ceil(sample_y))]
pixel_bot_left = img[int(np.ceil(sample_x)), int(np.floor(sample_y))]
pixel_bot_right = img[int(np.ceil(sample_x)), int(np.ceil(sample_y))]
img_resized_own[i, j] = (1.0 - (sample_x - np.floor(sample_x))) * (1.0 - (sample_y - np.floor(sample_y))) * pixel_top_left + \
(1.0 - (sample_x - np.floor(sample_x))) * (sample_y - np.floor(sample_y)) * pixel_top_right + \
(sample_x - np.floor(sample_x)) * (1.0 - (sample_y - np.floor(sample_y))) * pixel_bot_left + \
(sample_x - np.floor(sample_x)) * (sample_y - np.floor(sample_y)) * pixel_bot_right
# 4. Print results:
print "\n"
print "Org. image: \n", img
print "\n"
print "Resized image (OpenCV): \n", img_resized_opencv
print "\n"
print "Resized image (own): \n", img_resized_own
print "\n"
print "MSE between OpenCV <-> Own: ", np.mean(np.square(img_resized_opencv - img_resized_own))
print "\n"
Disclaimer:
This is just my theory that I tested via ~10 test cases. I do not claim that this is 100% true.

Binary clock with Lua, how to remove dots that aren't used?

I have the following binary clock that I grabbed from this wiki article (the one that's for v1.5.*) for the awesome WM:
binClock = wibox.widget.base.make_widget()
binClock.radius = 1.5
binClock.shift = 1.8
binClock.farShift = 2
binClock.border = 1
binClock.lineWidth = 1
binClock.colorActive = beautiful.bg_focus
binClock.fit = function(binClock, width, height)
local size = math.min(width, height)
return 6 * 2 * binClock.radius + 5 * binClock.shift + 2 * binClock.farShift + 2 * binClock.border + 2 * binClock.border, size
end
binClock.draw = function(binClock, wibox, cr, width, height)
local curTime = os.date("*t")
local column = {}
table.insert(column, string.format("%04d", binClock:dec_bin(string.sub(string.format("%02d", curTime.hour), 1, 1))))
table.insert(column, string.format("%04d", binClock:dec_bin(string.sub(string.format("%02d", curTime.hour), 2, 2))))
table.insert(column, string.format("%04d", binClock:dec_bin(string.sub(string.format("%02d", curTime.min), 1, 1))))
table.insert(column, string.format("%04d", binClock:dec_bin(string.sub(string.format("%02d", curTime.min), 2, 2))))
table.insert(column, string.format("%04d", binClock:dec_bin(string.sub(string.format("%02d", curTime.sec), 1, 1))))
table.insert(column, string.format("%04d", binClock:dec_bin(string.sub(string.format("%02d", curTime.sec), 2, 2))))
local bigColumn = 0
for i = 0, 5 do
if math.floor(i / 2) > bigColumn then
bigColumn = bigColumn + 1
end
for j = 0, 3 do
if string.sub(column[i + 1], j + 1, j + 1) == "0" then
active = false
else
active = true
end
binClock:draw_point(cr, bigColumn, i, j, active)
end
end
end
binClock.dec_bin = function(binClock, inNum)
inNum = tonumber(inNum)
local base, enum, outNum, rem = 2, "01", "", 0
while inNum > (base - 1) do
inNum, rem = math.floor(inNum / base), math.fmod(inNum, base)
outNum = string.sub(enum, rem + 1, rem + 1) .. outNum
end
outNum = inNum .. outNum
return outNum
end
binClock.draw_point = function(binClock, cr, bigColumn, column, row, active)
cr:arc(binClock.border + column * (2 * binClock.radius + binClock.shift) + bigColumn * binClock.farShift + binClock.radius,
binClock.border + row * (2 * binClock.radius + binClock.shift) + binClock.radius, 2, 0, 2 * math.pi)
if active then
cr:set_source_rgba(0, 0.5, 0, 1)
else
cr:set_source_rgba(0.5, 0.5, 0.5, 1)
end
cr:fill()
end
binClocktimer = timer { timeout = 1 }
binClocktimer:connect_signal("timeout", function() binClock:emit_signal("widget::updated") end)
binClocktimer:start()
First, if something isn't by default already in Lua that's because this is to be used in the config file for awesome. :)
OK, so what I need is some guidance actually. I am not very familiar with Lua currently, so some guidance is all I ask so I can learn. :)
OK, so first, this code outputs a normal binary clock, but every column has 4 dots (44,44,44), instead of a 23,34,34 setup for the dots, as it would be in a normal binary clock. What's controlling that in this code? So that I can pay around with it.
Next, what controls the color? Right now it's gray background and quite a dark green, I want to brighten both of those up.
And what controls the smoothing? Right now it's outputting circles, would like to see what it's like for it to output squares instead.
That's all I need help with, if you can point me to the code and some documentation for what I need, that should be more than enough. :)
Also, if somebody would be nice enough to add some comments, that also would be awesome. Don't have to be very detailed comments, but at least to the point where it gives an idea of what each thing does. :)
EDIT:
Found what modifies the colors, so figured that out. None of the first variables control if it's a square or circle BTW. :)
The draw_point function draws the dots.
The two loops in the draw function are what create the output and is where the columns come from. To do a 23/34/34 layout you would need to modify the inner loop skip the first X points based on the counter of the outer loop I believe.

Resources