Yaohong

为了真相不惜被羞辱

Simple AI expert Enhanced Loop

Simple AI expert Enhanced Loop

Habit: Daily plan, weekly plan, month plan, 10 minute reading, Daily self-examination

Loop1: Assumption->design a experiment->do->feedback->conclusion

Loop2: Choose a subject->Weekly Share to my classmates->Feedback and update -> Make another share;


The form of our body in future

The form of our body in future

  • 1.The human body consumes energy in the form of carbohydrate.
  • 2.The human body consumes energy in the form of carbohydrate and electric, part of our body are machine.
  • 3.The human body consumes energy in the form of nuclear in long long future, and we can calculate just like we are a super computer .

The Simple Implement of BatchNorm2D

The Simple Implement of BatchNorm2D

The first is that instead of whiteningthe features in layer inputs and outputs jointly, we will normalize each scalar feature independently, by making ithave the mean of zero and the variance of 1. For a layer with d-dimensional inputx = (x(1). . . x(d)), we will nor-malize each dimension

1.MyBatchNorm2D

import numpy as np;
class MyBatchNorm2D:

    def __init__(self):
        pass

    def forward(self, x):
        x = np.array(x);
        mean = np.mean(x);
        standard_deviation = np.sqrt(np.var(x) + 1e-05);
        x_norm = (x - mean) / standard_deviation;
        return x_norm;

input = [[[[ 1.1713, -10.7508],
          [-2.0155, -0.5290],
          [-0.2751,  1.0233]],
         [[-1.4446, -0.8337],
          [-1.0429, -0.8856],
          [ 5.3324,  7.6233]]],
        [[[ 2.1079,  1.6039],
          [-0.8938,  1.1655],
          [ 8.0355, -0.4911]],
         [[ 3.6337,  10.3400],
          [-1.5365,  0.7931],
          [ 0.8472,  1.1318]]]];
x = np.array(input);
bn = MyBatchNorm2D();
x_norm = bn.forward(input);
print("x_norm:", x_norm);

print("np.mean: ", np.mean(np.array(input)));
print("np.var: " , np.var(np.array(input)));
print("MyBatchNorm2D np.mean: ", np.mean(np.array(x_norm)));
print("MyBatchNorm2D np.var: " , np.var(np.array(x_norm)));

# OUTPUT:
# x_norm: [[[[ 0.0414345  -2.92181622]
#           [-0.75064805 -0.38117689]
#           [-0.31806977  0.00464894]]
#          [[-0.60875025 -0.4569104 ]
#           [-0.50890728 -0.4698102 ]
#           [ 1.07568036  1.64508601]]]
#         [[[ 0.27422743  0.14895769]
#           [-0.47184832  0.0399929 ]
#           [ 1.74753876 -0.3717568 ]]
#          [[ 0.65346666  2.3203247 ]
#           [-0.63159209 -0.05256752]
#           [-0.0391209   0.03161673]]]]
# np.mean:  1.0045958333333334
# np.var:  16.18707780123264
# MyBatchNorm2D np.mean:  0.0
# MyBatchNorm2D np.var:  0.9999993822236513

2.Using BatchNorm2d in torch

input = [[[[ 1.1713, -10.7508],
          [-2.0155, -0.5290],
          [-0.2751,  1.0233]],
         [[-1.4446, -0.8337],
          [-1.0429, -0.8856],
          [ 5.3324,  7.6233]]],
        [[[ 2.1079,  1.6039],
          [-0.8938,  1.1655],
          [ 8.0355, -0.4911]],
         [[ 3.6337,  10.3400],
          [-1.5365,  0.7931],
          [ 0.8472,  1.1318]]]];

import torch
import torch.nn as nn
input = torch.tensor(input);
bn = nn.BatchNorm2d(2, momentum=None, affine=False, track_running_stats=None)
x_norm = bn(input)
print("BatchNorm2d new_x:", x_norm);

import numpy as np;
print("BatchNorm2d np.mean: " , np.mean(np.array(x_norm)));
print("BatchNorm2d np.var: " , np.var(np.array(x_norm)));

# OUTPUT:
# BatchNorm2d new_x: tensor([[[[ 0.2864, -2.6606],
#                               [-0.5013, -0.1339],
#                               [-0.0711,  0.2498]],
#                              [[-0.9184, -0.7553],
#                               [-0.8112, -0.7692],
#                               [ 0.8903,  1.5017]]],
#                             [[[ 0.5179,  0.3933],
#                               [-0.2241,  0.2850],
#                               [ 1.9831, -0.1245]],
#                              [[ 0.4369,  2.2267],
#                               [-0.9429, -0.3212],
#                               [-0.3067, -0.2308]]]])
# BatchNorm2d np.mean:  -9.934108e-09
# BatchNorm2d np.var:  0.99999934

REFERENCE:

1.Torch nn.BatchNorm2d


model(x) vs model.forward(x)

model(x) vs model.forward(x)

__call__ magic method in nn.Module will invoke forward() method and take care of hooks and states that python allows, so we should use model(x) rather than call model.forward(x) directly.

REFERENCE:

1.Why there are different output between model.forward(input) and model(input)

2.Calling forward function without .forward()

3.torch.nn.module codes


How to extract knowledge?

How to extract knowledge?

I held the opinion before that to do knowledge extraction can be done only by summarizing, but it is not a good way. In contrast, put the knowledge back to a concrete scenario will work for user understandings.

I used to thought common truths are the most valuable of knowledge, but perhaps we need the knowledge with personal experiences.

Because it contains the problem that the author face and the way how one to think, while summary knowledge is only the result of thinking.


How to face the investment risk?

How to face the investment risk?

Investment risk is the expectation loss of our investment.

It is difficult to calculate the probability of loss sometimes, but we can assume that the loss have happened, then try to find out the reason of loss.

Before investing, we can try to answer the following two questions:

1.What cause the price of properties fall 50%?

  • Liquidity risk

  • Credit risk

2.How will you do if the price fell 50%?


DNN RNN CNN codes

Simple DNN RNN CNN example codes

1.DNN-Deep neural network


import numpy as np;
class myDNN:

    # 3 * 5 * 2
    def __init__(self, input, hidden, output):
        # hidden random weight 
        # Note: hidden_weight can be the shape of (input,hidden); correspondingly, `self.hidden_out` should equal `np.dot(input_data, self.hidden_weight)` to accord with hidden_weight shape.
        self.hidden_weight     = np.random.rand(hidden, input); 

        self.hidden_bias       = np.random.rand(hidden);

        # hidden random weight 
        self.output_weight     = np.random.rand(output,hidden);
        self.output_bias       = np.random.rand(output);

    # 
    def forward(self, input_data):
        self.hidden_out = np.dot(input_data, self.hidden_weight.T) + self.hidden_bias;

        self.output_out = np.dot(self.hidden_out, self.output_weight.T) + self.output_bias;

# Usage:
dnn = myDNN(3,5,3);
print("hidden_weight",dnn.hidden_weight)
print("hidden_bias:",dnn.hidden_bias)
print("output_weight",dnn.output_weight)
print("output_bias",dnn.output_bias)

x = np.array([1, 2, 3])  #inut
dnn.forward(x);
print("output_out",dnn.output_out)

# output:
# hidden_weight [[0.99663996 0.39342568 0.5312192 ]
#  [0.0798744  0.50312289 0.86241405]
#  [0.17138496 0.6761287  0.70645906]
#  [0.61662379 0.69389404 0.16623206]
#  [0.71213402 0.30800932 0.64149244]]
# hidden_bias: [0.81517457 0.56115705 0.3089624  0.84450962 0.93530796]
# output_weight [[0.34466034 0.31119367 0.12883636 0.34135026 0.43802589]
#  [0.31553914 0.16063241 0.8179255  0.52314575 0.79439618]
#  [0.86730239 0.25280671 0.20375421 0.78095429 0.67368635]]
# output_bias [0.5588883  0.98722366 0.21507382]
# output_out [ 6.8078659  11.30086755 11.16252686]

1.1 Use DNN in torch

import torch.nn as nn
class TorchDNN(nn.Module):

    def __init__(self, input, hidden, output):
        super(TorchDNN, self).__init__();
        self.layer_hidden = nn.Linear(input, hidden, bias = True);
        self.layer_output = nn.Linear(hidden, output, bias = True);

    # 
    def forward(self, input_data):
        self.hidden_out = self.layer_hidden(input_data);
        self.output_out = self.layer_output(self.hidden_out);

x = np.array([1, 2, 3])
torch_model = TorchDNN(len(x), 5, 3)
print(torch_model.state_dict())

# OrderedDict([('layer_hidden.weight', 
#  tensor([[-0.5216, -0.5690,  0.4181],
#         [-0.3142,  0.1489,  0.5071],
#         [ 0.0295,  0.3381,  0.4401],
#         [-0.4697,  0.0732, -0.0328],
#         [ 0.5250,  0.1540,  0.2086]])), 
#         ('layer_hidden.bias', tensor([-0.5134,  0.2645, -0.3366, -0.0597,  0.0159])), 
#         ('layer_output.weight', 
# tensor([[ 0.2770, -0.3408, -0.3145, -0.3686,  0.1060],
#         [ 0.1268,  0.0729, -0.3838,  0.2850,  0.1438],
#         [ 0.1645, -0.0497,  0.1029,  0.1088, -0.0536]])), 
#         ('layer_output.bias', tensor([ 0.0908, -0.1240,  0.2800]))])

2.RNN-Recurrent neural network


import numpy as np;
class myRNN:

    def __init__(self, input, hidden ):
        # random weight
        self.input_hidden_weight     = np.random.randint(-10000,10000,(hidden, input))/10000;
        self.hidden_hidden_weight    = np.random.randint(-10000,10000,(hidden))/10000;

        # random bias
        self.input_hidden_bias     = np.random.randint(-10000,10000,(hidden))/10000;
        self.hidden_hidden_bias     = np.random.randint(-10000,10000,(hidden))/10000;
        # self.input_hidden_bias      = np.zeros(hidden);
        # self.hidden_hidden_bias     = np.zeros(hidden);
        self.hidden_size            = hidden

   
    def forward(self, input_data):
        self.last_hidden_output = np.zeros([self.hidden_size]);
        output = []
        for item in input_data:
            # ht​=tanh(W_ih​ * x_t​ + b_ih  ​ +   W_hh​*h_(t−1)​+b_hh​)
            hidden_cur = np.dot(item, self.input_hidden_weight.T) + self.input_hidden_bias;
            hidden_pre = np.dot(self.last_hidden_output, self.hidden_hidden_weight.T)   + self.hidden_hidden_bias;

            hidden_output =  np.tanh( hidden_cur + hidden_pre )
            output.append(hidden_output)
            self.last_hidden_output = hidden_output;

        return np.array(output), hidden_output;

# diy_model = myRNN(w_ih, w_hh, hidden_size)
x = np.array([[1, 2, 3], [3, 4, 5], [5, 6, 7]]) 
input_size = 3;
hidden_size = 4;
diy_model = myRNN(input_size,hidden_size)
output, hidden_output = diy_model.forward(x)
print("myRNN process output: ", output)
print("myRNN hidden_output:", hidden_output)

# output:
# myRNN process output:  [[-0.62745049 -0.99314575 -0.96754221 -0.9965258 ]
#  [-0.99542912 -0.99962783 -0.99965698 -0.99998354]
#  [-0.99983032 -0.99992543 -0.9999868  -0.99999971]]
# myRNN hidden_output: [-0.99983032 -0.99992543 -0.9999868  -0.99999971]

2.1 Use RNN in torch

import torch.nn as nn;
import torch;
import numpy as np;
class TorchRNN(nn.Module):

    def __init__(self, input_size, hidden):
        super(TorchRNN,self).__init__();
        self.layer = nn.RNN(input_size, hidden, batch_first=True);

    def forward(self, x):
        return self.layer(x)


torch_model = TorchRNN(3, 4)
print(torch_model.state_dict())

x = np.array([[1, 2, 3], [3, 4, 5], [5, 6, 7]]) 
torch_x = torch.FloatTensor([x])
output, h = torch_model.forward(torch_x)
print("output:", output.detach().numpy())
print("h:",h.detach().numpy())

# output: 
# OrderedDict([('layer.weight_ih_l0', tensor([[ 0.0922,  0.2786, -0.4514],
#         [ 0.3809,  0.2628, -0.4460],
#         [-0.4951, -0.3599, -0.4961],
#         [ 0.3794,  0.3397,  0.3185]])), ('layer.weight_hh_l0', tensor([[-0.1330, -0.1843, -0.2618,  0.4246],
#         [ 0.4154, -0.3578, -0.4181, -0.4291],
#         [ 0.3608, -0.2349,  0.4631,  0.4873],
#         [ 0.4886,  0.0285, -0.0490,  0.2928]])), ('layer.bias_ih_l0', tensor([-0.1421, -0.3572, -0.2087, -0.0319])), ('layer.bias_hh_l0', tensor([-0.3799,  0.1126, -0.1766,  0.2630]))])
# output: [[[-0.8416229  -0.589054   -0.99585485  0.9778193 ]
#   [-0.45533973 -0.3993926  -0.9999862   0.99957436]
#   [-0.6221984   0.05736368 -0.99999994  0.9999955 ]]]
# h: [[[-0.6221984   0.05736368 -0.99999994  0.9999955 ]]]

3.CNN-Convolutional neural network

import numpy as np;
class MyCNN:

    # I don't know how do filters work.
    def __init__(self, in_channel, out_channel, kernel_size):
        # random weight
        # (out_channel, in_channel, kernel_size, kernel_size)
        # self.kernel_weight    = np.random.randint(-10000,10000,(out_channel, in_channel, kernel_size, kernel_size))/10000;
        self.kernel_weight = np.array([[[[ 0.0106, -0.1561,  0.0984],
                                          [ 0.1468,  0.1580, -0.1404],
                                          [ 0.0856,  0.0780,  0.0636]],
                                         [[-0.1620,  0.2318,  0.0486],
                                          [-0.2214, -0.2046,  0.1070],
                                          [ 0.1609,  0.0160, -0.0374]]],
                                        [[[ 0.1876, -0.2056,  0.1858],
                                          [-0.1288,  0.0065, -0.0145],
                                          [-0.1080,  0.1519,  0.0581]],
                                         [[-0.0749,  0.2289, -0.0890],
                                          [ 0.0611,  0.0398, -0.1293],
                                          [ 0.0911, -0.0264, -0.2104]]]]);
        self.in_channel     = in_channel;
        self.out_channel    = out_channel;
        self.kernel_size    = kernel_size;

    # c*h*w
    def forward(self, input_data):
        output = [];
        input_shape = input_data.shape;

        idx_start   = np.int(np.floor( (self.kernel_size)/2)) ;
        width       = input_shape[1];
        height      = input_shape[2];
        in_channel  = input_shape[0];

        for o_c in range(self.out_channel):
            piece_of_out_channel = np.zeros(( width-(idx_start*2), height-(idx_start*2) ));
            # print("piece_of_out_channel:", piece_of_out_channel.shape)
            # width
            for idx_height in range(idx_start, height - idx_start): 
                # height
                for idx_width in range(idx_start, width - idx_start ):
                    # kernel_shape_input
                    kernel_shape_input = input_data[:, idx_height-idx_start: idx_height+idx_start+1, idx_width-idx_start :idx_width+idx_start+1 ];

                    out = self.kernel_weight[o_c] * kernel_shape_input;
                    out = np.sum(out)

                    # assign value
                    idx_h = idx_height - idx_start;
                    idx_w = idx_width - idx_start
                    piece_of_out_channel[idx_h][idx_w]  = out;

            output.append(piece_of_out_channel);
        return output;



# x = np.random.randint(0,10000,(2, 6, 6))/100;
# x = random.astype(int)
x = np.array([[[61,93,18,31,2,49]
            ,[12,62,32,60,58,30]
            ,[49,64,38,74,59,29]
            ,[71,34,29,88,59,41]
            ,[91,72,36,94,79,29]
            ,[17,15,86,29,84,53]]

            ,[[31,25,15,16,35,20]
            ,[76,45,82,88,49,99]
            ,[56,46,82,72,26,55]
            ,[7, 86,32,29,82,91]
            ,[76,68,17,50,19,53]
            ,[87,21,58,35,81,46]]
            ]);
# print(x);
print("x.shape:",x.shape)

myCNN = MyCNN(x.shape[0], 2, 3);
print(myCNN.kernel_weight)
output = myCNN.forward(x)
print("myCNN output:",output)

# output:
# x.shape: (2, 6, 6)
# myCNN output: [array([[-2.5093,  9.0098, -0.2033, 28.9   ],
#        [ 6.5155, 27.3464,  0.7038, 14.5031],
#        [24.2218, 16.1092, 23.2223, 16.9067],
#        [29.6749,  2.0986, 16.8128, 45.025 ]]), 
#         array([[-14.77  ,  -4.3335,   5.0665,   3.2378],
#        [-28.2207,  18.1968,  11.889 , -27.3557],
#        [ -2.748 ,  22.5508,  10.6013, -19.0372],
#        [ 22.0148,   9.1788, -22.0313,   9.5176]])]

3.1 Use CNN in torch



import torch;
import torch.nn as nn;
class TorchCNN(nn.Module):

    def __init__(self, in_channel, out_channel, kernel_size ):
        super().__init__();
        self.conv2d = nn.Conv2d(in_channel, out_channel, kernel_size, bias=False);

    def forward(self, input_data):
        return self.conv2d(input_data);

in_channel = x.shape[0];
torchcnn = TorchCNN(in_channel, 2, 3);
print("torchcnn weight:", torchcnn.state_dict())
print("torchcnn weight shape:", torchcnn.state_dict()['conv2d.weight'].numpy().shape)
# torchcnn weight shape: (2, 2, 3, 3) => (out_channel, in_channel, kernel_size, kernel_size)
torch_x = torch.FloatTensor([x])
out = torchcnn.forward(torch_x);
print("TorchCNN out: ", out)


# output
# torchcnn weight: OrderedDict([('conv2d.weight', tensor(
#       [[[[ 0.0106, -0.1561,  0.0984],
#           [ 0.1468,  0.1580, -0.1404],
#           [ 0.0856,  0.0780,  0.0636]],
#          [[-0.1620,  0.2318,  0.0486],
#           [-0.2214, -0.2046,  0.1070],
#           [ 0.1609,  0.0160, -0.0374]]],
#         [[[ 0.1876, -0.2056,  0.1858],
#           [-0.1288,  0.0065, -0.0145],
#           [-0.1080,  0.1519,  0.0581]],
#          [[-0.0749,  0.2289, -0.0890],
#           [ 0.0611,  0.0398, -0.1293],
#           [ 0.0911, -0.0264, -0.2104]]]]))])
# TorchCNN out:  tensor([[[[ -2.5066,   9.0144,  -0.1983,  28.9003],
#           [  6.5160,  27.3456,   0.7094,  14.5056],
#           [ 24.2262,  16.1086,  23.2279,  16.9102],
#           [ 29.6763,   2.1047,  16.8210,  45.0250]],
#          [[-14.7564,  -4.3273,   5.0752,   3.2491],
#           [-28.2115,  18.1981,  11.8975, -27.3447],
#           [ -2.7442,  22.5540,  10.6096, -19.0247],
#           [ 22.0166,   9.1837, -22.0241,   9.5211]]]],
#        grad_fn=<MkldnnConvolutionBackward>)

Use Opencv stitching_detailed To Stitch Segmentation image

Use Opencv stitching_detailed To Stitch Segmentation image

Environment:

python version 3.7
opencv-python version 4.5.1.48

1.Download stitching_detailed file save it with file name stitching_detailed.py;

2.Run the command;

$python.exe stitching_detailed.py image_1.png image_2.png image_3.png image_4.png image_5.png image_6.png image_7.png image_8.png image_9.png origin.png  --features=brisk --matcher=affine

Note that: image 1~9 is Segmentation images and origin.png is a full picture.

REFERENCE:

stitching_detailed

stitching_detailed.py source codes is follow:

"""
Stitching sample (advanced)
===========================
Show how to use Stitcher API from python.
"""

# Python 2/3 compatibility
from __future__ import print_function

import argparse
from collections import OrderedDict

import cv2 as cv
import numpy as np

EXPOS_COMP_CHOICES = OrderedDict()
EXPOS_COMP_CHOICES['gain_blocks'] = cv.detail.ExposureCompensator_GAIN_BLOCKS
EXPOS_COMP_CHOICES['gain'] = cv.detail.ExposureCompensator_GAIN
EXPOS_COMP_CHOICES['channel'] = cv.detail.ExposureCompensator_CHANNELS
EXPOS_COMP_CHOICES['channel_blocks'] = cv.detail.ExposureCompensator_CHANNELS_BLOCKS
EXPOS_COMP_CHOICES['no'] = cv.detail.ExposureCompensator_NO

BA_COST_CHOICES = OrderedDict()
BA_COST_CHOICES['ray'] = cv.detail_BundleAdjusterRay
BA_COST_CHOICES['reproj'] = cv.detail_BundleAdjusterReproj
BA_COST_CHOICES['affine'] = cv.detail_BundleAdjusterAffinePartial
BA_COST_CHOICES['no'] = cv.detail_NoBundleAdjuster

FEATURES_FIND_CHOICES = OrderedDict()
try:
    cv.xfeatures2d_SURF.create() # check if the function can be called
    FEATURES_FIND_CHOICES['surf'] = cv.xfeatures2d_SURF.create
except (AttributeError, cv.error) as e:
    print("SURF not available")
# if SURF not available, ORB is default
FEATURES_FIND_CHOICES['orb'] = cv.ORB.create
try:
    FEATURES_FIND_CHOICES['sift'] = cv.xfeatures2d_SIFT.create
except AttributeError:
    print("SIFT not available")
try:
    FEATURES_FIND_CHOICES['brisk'] = cv.BRISK_create
except AttributeError:
    print("BRISK not available")
try:
    FEATURES_FIND_CHOICES['akaze'] = cv.AKAZE_create
except AttributeError:
    print("AKAZE not available")

SEAM_FIND_CHOICES = OrderedDict()
SEAM_FIND_CHOICES['gc_color'] = cv.detail_GraphCutSeamFinder('COST_COLOR')
SEAM_FIND_CHOICES['gc_colorgrad'] = cv.detail_GraphCutSeamFinder('COST_COLOR_GRAD')
SEAM_FIND_CHOICES['dp_color'] = cv.detail_DpSeamFinder('COLOR')
SEAM_FIND_CHOICES['dp_colorgrad'] = cv.detail_DpSeamFinder('COLOR_GRAD')
SEAM_FIND_CHOICES['voronoi'] = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_VORONOI_SEAM)
SEAM_FIND_CHOICES['no'] = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_NO)

ESTIMATOR_CHOICES = OrderedDict()
ESTIMATOR_CHOICES['homography'] = cv.detail_HomographyBasedEstimator
ESTIMATOR_CHOICES['affine'] = cv.detail_AffineBasedEstimator

WARP_CHOICES = (
    'spherical',
    'plane',
    'affine',
    'cylindrical',
    'fisheye',
    'stereographic',
    'compressedPlaneA2B1',
    'compressedPlaneA1.5B1',
    'compressedPlanePortraitA2B1',
    'compressedPlanePortraitA1.5B1',
    'paniniA2B1',
    'paniniA1.5B1',
    'paniniPortraitA2B1',
    'paniniPortraitA1.5B1',
    'mercator',
    'transverseMercator',
)

WAVE_CORRECT_CHOICES = OrderedDict()
WAVE_CORRECT_CHOICES['horiz'] = cv.detail.WAVE_CORRECT_HORIZ
WAVE_CORRECT_CHOICES['no'] = None
WAVE_CORRECT_CHOICES['vert'] = cv.detail.WAVE_CORRECT_VERT

BLEND_CHOICES = ('multiband', 'feather', 'no',)

parser = argparse.ArgumentParser(
    prog="stitching_detailed.py", description="Rotation model images stitcher"
)
parser.add_argument(
    'img_names', nargs='+',
    help="Files to stitch", type=str
)
parser.add_argument(
    '--try_cuda',
    action='store',
    default=False,
    help="Try to use CUDA. The default value is no. All default values are for CPU mode.",
    type=bool, dest='try_cuda'
)
parser.add_argument(
    '--work_megapix', action='store', default=0.6,
    help="Resolution for image registration step. The default is 0.6 Mpx",
    type=float, dest='work_megapix'
)
parser.add_argument(
    '--features', action='store', default=list(FEATURES_FIND_CHOICES.keys())[0],
    help="Type of features used for images matching. The default is '%s'." % list(FEATURES_FIND_CHOICES.keys())[0],
    choices=FEATURES_FIND_CHOICES.keys(),
    type=str, dest='features'
)
parser.add_argument(
    '--matcher', action='store', default='homography',
    help="Matcher used for pairwise image matching. The default is 'homography'.",
    choices=('homography', 'affine'),
    type=str, dest='matcher'
)
parser.add_argument(
    '--estimator', action='store', default=list(ESTIMATOR_CHOICES.keys())[0],
    help="Type of estimator used for transformation estimation. The default is '%s'." % list(ESTIMATOR_CHOICES.keys())[0],
    choices=ESTIMATOR_CHOICES.keys(),
    type=str, dest='estimator'
)
parser.add_argument(
    '--match_conf', action='store',
    help="Confidence for feature matching step. The default is 0.3 for ORB and 0.65 for other feature types.",
    type=float, dest='match_conf'
)
parser.add_argument(
    '--conf_thresh', action='store', default=1.0,
    help="Threshold for two images are from the same panorama confidence.The default is 1.0.",
    type=float, dest='conf_thresh'
)
parser.add_argument(
    '--ba', action='store', default=list(BA_COST_CHOICES.keys())[0],
    help="Bundle adjustment cost function. The default is '%s'." % list(BA_COST_CHOICES.keys())[0],
    choices=BA_COST_CHOICES.keys(),
    type=str, dest='ba'
)
parser.add_argument(
    '--ba_refine_mask', action='store', default='xxxxx',
    help="Set refinement mask for bundle adjustment. It looks like 'x_xxx', "
         "where 'x' means refine respective parameter and '_' means don't refine, "
         "and has the following format:<fx><skew><ppx><aspect><ppy>. "
         "The default mask is 'xxxxx'. "
         "If bundle adjustment doesn't support estimation of selected parameter then "
         "the respective flag is ignored.",
    type=str, dest='ba_refine_mask'
)
parser.add_argument(
    '--wave_correct', action='store', default=list(WAVE_CORRECT_CHOICES.keys())[0],
    help="Perform wave effect correction. The default is '%s'" % list(WAVE_CORRECT_CHOICES.keys())[0],
    choices=WAVE_CORRECT_CHOICES.keys(),
    type=str, dest='wave_correct'
)
parser.add_argument(
    '--save_graph', action='store', default=None,
    help="Save matches graph represented in DOT language to <file_name> file.",
    type=str, dest='save_graph'
)
parser.add_argument(
    '--warp', action='store', default=WARP_CHOICES[0],
    help="Warp surface type. The default is '%s'." % WARP_CHOICES[0],
    choices=WARP_CHOICES,
    type=str, dest='warp'
)
parser.add_argument(
    '--seam_megapix', action='store', default=0.1,
    help="Resolution for seam estimation step. The default is 0.1 Mpx.",
    type=float, dest='seam_megapix'
)
parser.add_argument(
    '--seam', action='store', default=list(SEAM_FIND_CHOICES.keys())[0],
    help="Seam estimation method. The default is '%s'." % list(SEAM_FIND_CHOICES.keys())[0],
    choices=SEAM_FIND_CHOICES.keys(),
    type=str, dest='seam'
)
parser.add_argument(
    '--compose_megapix', action='store', default=-1,
    help="Resolution for compositing step. Use -1 for original resolution. The default is -1",
    type=float, dest='compose_megapix'
)
parser.add_argument(
    '--expos_comp', action='store', default=list(EXPOS_COMP_CHOICES.keys())[0],
    help="Exposure compensation method. The default is '%s'." % list(EXPOS_COMP_CHOICES.keys())[0],
    choices=EXPOS_COMP_CHOICES.keys(),
    type=str, dest='expos_comp'
)
parser.add_argument(
    '--expos_comp_nr_feeds', action='store', default=1,
    help="Number of exposure compensation feed.",
    type=np.int32, dest='expos_comp_nr_feeds'
)
parser.add_argument(
    '--expos_comp_nr_filtering', action='store', default=2,
    help="Number of filtering iterations of the exposure compensation gains.",
    type=float, dest='expos_comp_nr_filtering'
)
parser.add_argument(
    '--expos_comp_block_size', action='store', default=32,
    help="BLock size in pixels used by the exposure compensator. The default is 32.",
    type=np.int32, dest='expos_comp_block_size'
)
parser.add_argument(
    '--blend', action='store', default=BLEND_CHOICES[0],
    help="Blending method. The default is '%s'." % BLEND_CHOICES[0],
    choices=BLEND_CHOICES,
    type=str, dest='blend'
)
parser.add_argument(
    '--blend_strength', action='store', default=5,
    help="Blending strength from [0,100] range. The default is 5",
    type=np.int32, dest='blend_strength'
)
parser.add_argument(
    '--output', action='store', default='result.jpg',
    help="The default is 'result.jpg'",
    type=str, dest='output'
)
parser.add_argument(
    '--timelapse', action='store', default=None,
    help="Output warped images separately as frames of a time lapse movie, "
         "with 'fixed_' prepended to input file names.",
    type=str, dest='timelapse'
)
parser.add_argument(
    '--rangewidth', action='store', default=-1,
    help="uses range_width to limit number of images to match with.",
    type=int, dest='rangewidth'
)

__doc__ += '\n' + parser.format_help()


def get_matcher(args):
    try_cuda = args.try_cuda
    matcher_type = args.matcher
    if args.match_conf is None:
        if args.features == 'orb':
            match_conf = 0.3
        else:
            match_conf = 0.65
    else:
        match_conf = args.match_conf
    range_width = args.rangewidth
    if matcher_type == "affine":
        matcher = cv.detail_AffineBestOf2NearestMatcher(False, try_cuda, match_conf)
    elif range_width == -1:
        matcher = cv.detail.BestOf2NearestMatcher_create(try_cuda, match_conf)
    else:
        matcher = cv.detail.BestOf2NearestRangeMatcher_create(range_width, try_cuda, match_conf)
    return matcher


def get_compensator(args):
    expos_comp_type = EXPOS_COMP_CHOICES[args.expos_comp]
    expos_comp_nr_feeds = args.expos_comp_nr_feeds
    expos_comp_block_size = args.expos_comp_block_size
    # expos_comp_nr_filtering = args.expos_comp_nr_filtering
    if expos_comp_type == cv.detail.ExposureCompensator_CHANNELS:
        compensator = cv.detail_ChannelsCompensator(expos_comp_nr_feeds)
        # compensator.setNrGainsFilteringIterations(expos_comp_nr_filtering)
    elif expos_comp_type == cv.detail.ExposureCompensator_CHANNELS_BLOCKS:
        compensator = cv.detail_BlocksChannelsCompensator(
            expos_comp_block_size, expos_comp_block_size,
            expos_comp_nr_feeds
        )
        # compensator.setNrGainsFilteringIterations(expos_comp_nr_filtering)
    else:
        compensator = cv.detail.ExposureCompensator_createDefault(expos_comp_type)
    return compensator


def main():
    args = parser.parse_args()
    img_names = args.img_names
    print(img_names)
    work_megapix = args.work_megapix
    seam_megapix = args.seam_megapix
    compose_megapix = args.compose_megapix
    conf_thresh = args.conf_thresh
    ba_refine_mask = args.ba_refine_mask
    wave_correct = WAVE_CORRECT_CHOICES[args.wave_correct]
    if args.save_graph is None:
        save_graph = False
    else:
        save_graph = True
    warp_type = args.warp
    blend_type = args.blend
    blend_strength = args.blend_strength
    result_name = args.output
    if args.timelapse is not None:
        timelapse = True
        if args.timelapse == "as_is":
            timelapse_type = cv.detail.Timelapser_AS_IS
        elif args.timelapse == "crop":
            timelapse_type = cv.detail.Timelapser_CROP
        else:
            print("Bad timelapse method")
            exit()
    else:
        timelapse = False
    finder = FEATURES_FIND_CHOICES[args.features]()
    seam_work_aspect = 1
    full_img_sizes = []
    features = []
    images = []
    is_work_scale_set = False
    is_seam_scale_set = False
    is_compose_scale_set = False
    for name in img_names:
        full_img = cv.imread(cv.samples.findFile(name))
        if full_img is None:
            print("Cannot read image ", name)
            exit()
        full_img_sizes.append((full_img.shape[1], full_img.shape[0]))
        if work_megapix < 0:
            img = full_img
            work_scale = 1
            is_work_scale_set = True
        else:
            if is_work_scale_set is False:
                work_scale = min(1.0, np.sqrt(work_megapix * 1e6 / (full_img.shape[0] * full_img.shape[1])))
                is_work_scale_set = True
            img = cv.resize(src=full_img, dsize=None, fx=work_scale, fy=work_scale, interpolation=cv.INTER_LINEAR_EXACT)
        if is_seam_scale_set is False:
            seam_scale = min(1.0, np.sqrt(seam_megapix * 1e6 / (full_img.shape[0] * full_img.shape[1])))
            seam_work_aspect = seam_scale / work_scale
            is_seam_scale_set = True
        img_feat = cv.detail.computeImageFeatures2(finder, img)
        features.append(img_feat)
        img = cv.resize(src=full_img, dsize=None, fx=seam_scale, fy=seam_scale, interpolation=cv.INTER_LINEAR_EXACT)
        images.append(img)

    matcher = get_matcher(args)
    p = matcher.apply2(features)
    matcher.collectGarbage()

    if save_graph:
        with open(args.save_graph, 'w') as fh:
            fh.write(cv.detail.matchesGraphAsString(img_names, p, conf_thresh))

    indices = cv.detail.leaveBiggestComponent(features, p, conf_thresh)
    img_subset = []
    img_names_subset = []
    full_img_sizes_subset = []
    for i in range(len(indices)):
        img_names_subset.append(img_names[indices[i, 0]])
        img_subset.append(images[indices[i, 0]])
        full_img_sizes_subset.append(full_img_sizes[indices[i, 0]])
    images = img_subset
    img_names = img_names_subset
    full_img_sizes = full_img_sizes_subset
    num_images = len(img_names)
    if num_images < 2:
        print("Need more images")
        exit()

    estimator = ESTIMATOR_CHOICES[args.estimator]()
    b, cameras = estimator.apply(features, p, None)
    if not b:
        print("Homography estimation failed.")
        exit()
    for cam in cameras:
        cam.R = cam.R.astype(np.float32)

    adjuster = BA_COST_CHOICES[args.ba]()
    adjuster.setConfThresh(1)
    refine_mask = np.zeros((3, 3), np.uint8)
    if ba_refine_mask[0] == 'x':
        refine_mask[0, 0] = 1
    if ba_refine_mask[1] == 'x':
        refine_mask[0, 1] = 1
    if ba_refine_mask[2] == 'x':
        refine_mask[0, 2] = 1
    if ba_refine_mask[3] == 'x':
        refine_mask[1, 1] = 1
    if ba_refine_mask[4] == 'x':
        refine_mask[1, 2] = 1
    adjuster.setRefinementMask(refine_mask)
    b, cameras = adjuster.apply(features, p, cameras)
    if not b:
        print("Camera parameters adjusting failed.")
        exit()
    focals = []
    for cam in cameras:
        focals.append(cam.focal)
    focals.sort()
    if len(focals) % 2 == 1:
        warped_image_scale = focals[len(focals) // 2]
    else:
        warped_image_scale = (focals[len(focals) // 2] + focals[len(focals) // 2 - 1]) / 2
    if wave_correct is not None:
        rmats = []
        for cam in cameras:
            rmats.append(np.copy(cam.R))
        rmats = cv.detail.waveCorrect(rmats, wave_correct)
        for idx, cam in enumerate(cameras):
            cam.R = rmats[idx]
    corners = []
    masks_warped = []
    images_warped = []
    sizes = []
    masks = []
    for i in range(0, num_images):
        um = cv.UMat(255 * np.ones((images[i].shape[0], images[i].shape[1]), np.uint8))
        masks.append(um)

    warper = cv.PyRotationWarper(warp_type, warped_image_scale * seam_work_aspect)  # warper could be nullptr?
    for idx in range(0, num_images):
        K = cameras[idx].K().astype(np.float32)
        swa = seam_work_aspect
        K[0, 0] *= swa
        K[0, 2] *= swa
        K[1, 1] *= swa
        K[1, 2] *= swa
        corner, image_wp = warper.warp(images[idx], K, cameras[idx].R, cv.INTER_LINEAR, cv.BORDER_REFLECT)
        corners.append(corner)
        sizes.append((image_wp.shape[1], image_wp.shape[0]))
        images_warped.append(image_wp)
        p, mask_wp = warper.warp(masks[idx], K, cameras[idx].R, cv.INTER_NEAREST, cv.BORDER_CONSTANT)
        masks_warped.append(mask_wp.get())

    images_warped_f = []
    for img in images_warped:
        imgf = img.astype(np.float32)
        images_warped_f.append(imgf)

    compensator = get_compensator(args)
    compensator.feed(corners=corners, images=images_warped, masks=masks_warped)

    seam_finder = SEAM_FIND_CHOICES[args.seam]
    seam_finder.find(images_warped_f, corners, masks_warped)
    compose_scale = 1
    corners = []
    sizes = []
    blender = None
    timelapser = None
    # https://github.com/opencv/opencv/blob/master/samples/cpp/stitching_detailed.cpp#L725 ?
    for idx, name in enumerate(img_names):
        full_img = cv.imread(name)
        if not is_compose_scale_set:
            if compose_megapix > 0:
                compose_scale = min(1.0, np.sqrt(compose_megapix * 1e6 / (full_img.shape[0] * full_img.shape[1])))
            is_compose_scale_set = True
            compose_work_aspect = compose_scale / work_scale
            warped_image_scale *= compose_work_aspect
            warper = cv.PyRotationWarper(warp_type, warped_image_scale)
            for i in range(0, len(img_names)):
                cameras[i].focal *= compose_work_aspect
                cameras[i].ppx *= compose_work_aspect
                cameras[i].ppy *= compose_work_aspect
                sz = (full_img_sizes[i][0] * compose_scale, full_img_sizes[i][1] * compose_scale)
                K = cameras[i].K().astype(np.float32)
                roi = warper.warpRoi(sz, K, cameras[i].R)
                corners.append(roi[0:2])
                sizes.append(roi[2:4])
        if abs(compose_scale - 1) > 1e-1:
            img = cv.resize(src=full_img, dsize=None, fx=compose_scale, fy=compose_scale,
                            interpolation=cv.INTER_LINEAR_EXACT)
        else:
            img = full_img
        _img_size = (img.shape[1], img.shape[0])
        K = cameras[idx].K().astype(np.float32)
        corner, image_warped = warper.warp(img, K, cameras[idx].R, cv.INTER_LINEAR, cv.BORDER_REFLECT)
        mask = 255 * np.ones((img.shape[0], img.shape[1]), np.uint8)
        p, mask_warped = warper.warp(mask, K, cameras[idx].R, cv.INTER_NEAREST, cv.BORDER_CONSTANT)
        compensator.apply(idx, corners[idx], image_warped, mask_warped)
        image_warped_s = image_warped.astype(np.int16)
        dilated_mask = cv.dilate(masks_warped[idx], None)
        seam_mask = cv.resize(dilated_mask, (mask_warped.shape[1], mask_warped.shape[0]), 0, 0, cv.INTER_LINEAR_EXACT)
        mask_warped = cv.bitwise_and(seam_mask, mask_warped)
        if blender is None and not timelapse:
            blender = cv.detail.Blender_createDefault(cv.detail.Blender_NO)
            dst_sz = cv.detail.resultRoi(corners=corners, sizes=sizes)
            blend_width = np.sqrt(dst_sz[2] * dst_sz[3]) * blend_strength / 100
            if blend_width < 1:
                blender = cv.detail.Blender_createDefault(cv.detail.Blender_NO)
            elif blend_type == "multiband":
                blender = cv.detail_MultiBandBlender()
                blender.setNumBands((np.log(blend_width) / np.log(2.) - 1.).astype(np.int))
            elif blend_type == "feather":
                blender = cv.detail_FeatherBlender()
                blender.setSharpness(1. / blend_width)
            blender.prepare(dst_sz)
        elif timelapser is None and timelapse:
            timelapser = cv.detail.Timelapser_createDefault(timelapse_type)
            timelapser.initialize(corners, sizes)
        if timelapse:
            ma_tones = np.ones((image_warped_s.shape[0], image_warped_s.shape[1]), np.uint8)
            timelapser.process(image_warped_s, ma_tones, corners[idx])
            pos_s = img_names[idx].rfind("/")
            if pos_s == -1:
                fixed_file_name = "fixed_" + img_names[idx]
            else:
                fixed_file_name = img_names[idx][:pos_s + 1] + "fixed_" + img_names[idx][pos_s + 1:]
            cv.imwrite(fixed_file_name, timelapser.getDst())
        else:
            blender.feed(cv.UMat(image_warped_s), mask_warped, corners[idx])
    if not timelapse:
        result = None
        result_mask = None
        result, result_mask = blender.blend(result, result_mask)
        cv.imwrite(result_name, result)
        zoom_x = 600.0 / result.shape[1]
        dst = cv.normalize(src=result, dst=None, alpha=255., norm_type=cv.NORM_MINMAX, dtype=cv.CV_8U)
        dst = cv.resize(dst, dsize=None, fx=zoom_x, fy=zoom_x)
        cv.imshow(result_name, dst)
        cv.waitKey()

    print("Done")


if __name__ == '__main__':
    print(__doc__)
    main()
    cv.destroyAllWindows()

How to categorize our money

How to categorize our invest money?

I think sleep peacefully at in night is the most important thing when we do the investment. I don’t need to worry about that I can’t pay my next monthly rent for the apartment after investing.

I believe that to avoid wake up at midnight is categorize our money. We can divide our cash into four categories.

The first category is called daily cash, it used to pay our daily cost. Apparently this type of money can not be invested to high risk stocks, or we might wake up at midnight.


2021-04-14 Diary

2021-04-14 Diary

While I was sitting on the chair searching on the internet, my little baby looked at me and was going to cry in the bedroom. I known he was tired and need to go to bed. So I close the Mac and going in the bedroom. When I clapped and open my hands to hold him, he laughed happily and came to me.

I held him to the bed, but as soon as he sit on the bed, he started to cry and crawled slowly to the bedside cupboard. I thought he may want to milk, but his mother was taking a bath. My little baby often milked before he go to bed.