大神的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
针对上面两幅图,第一张的long_edge=0,2
,第二张的long_edge=1,3
注意:这里头尾都是针对最长边上的操做
注意:头和尾是按照标签点的顺序进行的,排在前面为头,排在后面为尾
这部分比较简单,建议由须要的读者直接读取一个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和LNMS都比较简单,大概看一下就行了
这里主要是说明一下几个参数:
pixel_threshold = 0.9 #内部点阈值(目标点几率) side_vertex_pixel_threshold = 0.9 #内部头尾点的阈值 ##头尾点取值范围,head->[0,trunc_threshold] tail->[1-trunc_threshold,1],变大以后检测能力变强 trunc_threshold = 0.1
其实这个项目的思路很简单,看一下就明白,可是具体实现仍是有点棘手,难点在于标签的制做
边界点负责回归边界,这个边界如何肯定?如何肯定头和尾?
具体代码的注释写在里面了,还有不少小细节看笔者注释便可
下载地址