AdvanceEast源碼理解

文章思路

大神的github和我的網站已經對此進行了說明,這裏再也不贅述。。。git

源碼理解

一. 標籤點形式

  • 給四個點排列順序制定規則

'''github

按順序排列四個點,逆時針旋轉,且第一個點爲左上角點(剛開始選擇最左邊的點,

​ 若是最後計算的第二個點的Y比第一個點大,那就讓最後一個點作爲第一個點,其餘點依次右移)app

  • 1.以最小的X座標爲起點(起名爲A)less

  • 2.其餘三個點和第一個點(A)連線造成夾角,取中間的點爲第三個點(起名C)ide

  • 3.以AC爲連線,在AC上方爲D,下方爲B網站

  • 4.最後比較AC和BD的斜率,AC>BD ===> 順序調整爲DABC AC<BD ===> 維持ABCD.net

  • 5.感受第四步沒啥意義,只要是順序就行了,不必那麼苛刻。。。。debug

'''3d

  • 下面給出一些例子

圖1.1

圖1.2

  • 注意長邊的位置

針對上面兩幅圖,第一張的long_edge=0,2,第二張的long_edge=1,3

二. 標籤切邊

  • 以最短邊的0.3進行縮放當作內部點

圖1.3

  • 以最短邊的0.6做爲頭尾點

注意:這裏頭尾都是針對最長邊上的操做

注意:頭和尾是按照標籤點的順序進行的,排在前面爲頭,排在後面爲尾

圖1.4

圖1.5

三. loss計算

這部分比較簡單,建議由須要的讀者直接讀取一個data進行debug便可:

#input : 1*w*h*3
#label : 1*160*160*7(batch,w,h,type)
def quad_loss(y_true, y_pred):
    # loss for inside_score
    logits = y_pred[:, :, :, :1]
    labels = y_true[:, :, :, :1]
    # balance positive and negative samples in an image
    beta = 1 - tf.reduce_mean(labels)
    # first apply sigmoid activation
    predicts = tf.nn.sigmoid(logits)
    # log +epsilon for stable cal
    inside_score_loss = tf.reduce_mean(
        -1 * (beta * labels * tf.log(predicts + cfg.epsilon) +
              (1 - beta) * (1 - labels) * tf.log(1 - predicts + cfg.epsilon)))
    inside_score_loss *= cfg.lambda_inside_score_loss

    # loss for side_vertex_code
    vertex_logits = y_pred[:, :, :, 1:3]
    vertex_labels = y_true[:, :, :, 1:3]
    vertex_beta = 1 - (tf.reduce_mean(y_true[:, :, :, 1:2])
                       / (tf.reduce_mean(labels) + cfg.epsilon))
    vertex_predicts = tf.nn.sigmoid(vertex_logits)
    pos = -1 * vertex_beta * vertex_labels * tf.log(vertex_predicts +
                                                    cfg.epsilon)
    neg = -1 * (1 - vertex_beta) * (1 - vertex_labels) * tf.log(
        1 - vertex_predicts + cfg.epsilon)
    positive_weights = tf.cast(tf.equal(y_true[:, :, :, 0], 1), tf.float32)
    side_vertex_code_loss = \
        tf.reduce_sum(tf.reduce_sum(pos + neg, axis=-1) * positive_weights) / (
                tf.reduce_sum(positive_weights) + cfg.epsilon)
    side_vertex_code_loss *= cfg.lambda_side_vertex_code_loss

    # loss for side_vertex_coord delta
    g_hat = y_pred[:, :, :, 3:]
    g_true = y_true[:, :, :, 3:]
    vertex_weights = tf.cast(tf.equal(y_true[:, :, :, 1], 1), tf.float32)
    pixel_wise_smooth_l1norm = smooth_l1_loss(g_hat, g_true, vertex_weights)
    side_vertex_coord_loss = tf.reduce_sum(pixel_wise_smooth_l1norm) / (
            tf.reduce_sum(vertex_weights) + cfg.epsilon)
    side_vertex_coord_loss *= cfg.lambda_side_vertex_coord_loss
    return inside_score_loss + side_vertex_code_loss + side_vertex_coord_loss


def smooth_l1_loss(prediction_tensor, target_tensor, weights):
    n_q = tf.reshape(quad_norm(target_tensor), tf.shape(weights))
    diff = prediction_tensor - target_tensor
    abs_diff = tf.abs(diff)
    abs_diff_lt_1 = tf.less(abs_diff, 1)
    pixel_wise_smooth_l1norm = (tf.reduce_sum(
        tf.where(abs_diff_lt_1, 0.5 * tf.square(abs_diff), abs_diff - 0.5),
        axis=-1) / n_q) * weights
    return pixel_wise_smooth_l1norm


def quad_norm(g_true):
    shape = tf.shape(g_true)
    delta_xy_matrix = tf.reshape(g_true, [-1, 2, 2])
    diff = delta_xy_matrix[:, 0:1, :] - delta_xy_matrix[:, 1:2, :]
    square = tf.square(diff)
    distance = tf.sqrt(tf.reduce_sum(square, axis=-1))
    distance *= 4.0
    distance += cfg.epsilon
    return tf.reshape(distance, shape[:-1])

if __name__ == '__main__':
    x, y = data_generator.gen(1)
    loss_t = quad_loss(y,y)

四. NMS

這部分沒仔細看,傳統的NMS和LNMS都比較簡單,大概看一下就行了

這裏主要是說明一下幾個參數:

pixel_threshold = 0.9 #內部點閾值(目標點機率)
side_vertex_pixel_threshold = 0.9 #內部頭尾點的閾值
##頭尾點取值範圍,head->[0,trunc_threshold] tail->[1-trunc_threshold,1],變大以後檢測能力變強
trunc_threshold = 0.1

最後說明

其實這個項目的思路很簡單,看一下就明白,可是具體實現仍是有點棘手,難點在於標籤的製做

邊界點負責迴歸邊界,這個邊界如何肯定?如何肯定頭和尾?

具體代碼的註釋寫在裏面了,還有不少小細節看筆者註釋便可
下載地址

相關文章
相關標籤/搜索