From ccb821f3c40988de0745d2f0af3cb2a909a9f1f0 Mon Sep 17 00:00:00 2001 From: C-Achard Date: Mon, 26 Jan 2026 13:32:07 +0100 Subject: [PATCH 1/3] Add duplication notes to graph and pose modules Added comments indicating duplication between dlclive/graph.py and dlclive/pose_estimation_tensorflow/graph.py, as well as between dlclive/pose.py and dlclive/pose_estimation_tensorflow/pose.py. Marked the TensorFlow-specific files in the root as candidates for deletion since only the versions in pose_estimation_tensorflow are used. --- dlclive/graph.py | 5 ++++- dlclive/pose.py | 5 ++++- dlclive/pose_estimation_tensorflow/graph.py | 3 ++- dlclive/pose_estimation_tensorflow/pose.py | 3 ++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/dlclive/graph.py b/dlclive/graph.py index 72b3b76..fd60a87 100644 --- a/dlclive/graph.py +++ b/dlclive/graph.py @@ -5,7 +5,10 @@ Licensed under GNU Lesser General Public License v3.0 """ - +# NOTE DUPLICATED @C-Achard 2026-26-01: Duplication between this file +# and dlclive/pose_estimation_tensorflow/graph.py +# As this is tensorflow-specific and only the other graph.py is used, +# this one is candidate for deletion. import tensorflow as tf vers = (tf.__version__).split(".") diff --git a/dlclive/pose.py b/dlclive/pose.py index 3e69bb9..4cc80f8 100644 --- a/dlclive/pose.py +++ b/dlclive/pose.py @@ -5,7 +5,10 @@ Licensed under GNU Lesser General Public License v3.0 """ - +# NOTE DUPLICATED @C-Achard 2026-26-01: Duplication between this file +# and dlclive/pose_estimation_tensorflow/pose.py +# As this is tensorflow-specific and only the other pose.py is used, +# this one is candidate for deletion. import numpy as np diff --git a/dlclive/pose_estimation_tensorflow/graph.py b/dlclive/pose_estimation_tensorflow/graph.py index 9c9769b..5f6b383 100644 --- a/dlclive/pose_estimation_tensorflow/graph.py +++ b/dlclive/pose_estimation_tensorflow/graph.py @@ -5,7 +5,8 @@ Licensed under GNU Lesser General Public License v3.0 """ - +# NOTE DUPLICATED @C-Achard 2026-26-01: Duplication between this file +# and dlclive/graph.py import tensorflow as tf vers = (tf.__version__).split(".") diff --git a/dlclive/pose_estimation_tensorflow/pose.py b/dlclive/pose_estimation_tensorflow/pose.py index 3e69bb9..b14ee67 100644 --- a/dlclive/pose_estimation_tensorflow/pose.py +++ b/dlclive/pose_estimation_tensorflow/pose.py @@ -5,7 +5,8 @@ Licensed under GNU Lesser General Public License v3.0 """ - +# NOTE DUPLICATED @C-Achard 2026-26-01: Duplication between this file +# and dlclive/pose.py import numpy as np From 0305f6bda862d43005c0266e8f16e911b03b03b8 Mon Sep 17 00:00:00 2001 From: C-Achard Date: Mon, 26 Jan 2026 13:34:43 +0100 Subject: [PATCH 2/3] Remove duplicated TensorFlow-specific graph and pose modules Deleted dlclive/graph.py and dlclive/pose.py, which were duplicates of files in dlclive/pose_estimation_tensorflow/. These files were TensorFlow-specific and not used elsewhere --- dlclive/graph.py | 142 ----------------------------------------------- dlclive/pose.py | 123 ---------------------------------------- 2 files changed, 265 deletions(-) delete mode 100644 dlclive/graph.py delete mode 100644 dlclive/pose.py diff --git a/dlclive/graph.py b/dlclive/graph.py deleted file mode 100644 index fd60a87..0000000 --- a/dlclive/graph.py +++ /dev/null @@ -1,142 +0,0 @@ -""" -DeepLabCut Toolbox (deeplabcut.org) -© A. & M. Mathis Labs - -Licensed under GNU Lesser General Public License v3.0 -""" - -# NOTE DUPLICATED @C-Achard 2026-26-01: Duplication between this file -# and dlclive/pose_estimation_tensorflow/graph.py -# As this is tensorflow-specific and only the other graph.py is used, -# this one is candidate for deletion. -import tensorflow as tf - -vers = (tf.__version__).split(".") -if int(vers[0]) == 2 or int(vers[0]) == 1 and int(vers[1]) > 12: - tf = tf.compat.v1 -else: - tf = tf - - -def read_graph(file): - """ - Loads the graph from a protobuf file - - Parameters - ----------- - file : string - path to the protobuf file - - Returns - -------- - graph_def :class:`tensorflow.tf.compat.v1.GraphDef` - The graph definition of the DeepLabCut model found at the object's path - """ - - with tf.io.gfile.GFile(file, "rb") as f: - graph_def = tf.GraphDef() - graph_def.ParseFromString(f.read()) - return graph_def - - -def finalize_graph(graph_def): - """ - Finalize the graph and get inputs to model - - Parameters - ----------- - graph_def :class:`tensorflow.compat.v1.GraphDef` - The graph of the DeepLabCut model, read using the :func:`read_graph` method - - Returns - -------- - graph :class:`tensorflow.compat.v1.GraphDef` - The finalized graph of the DeepLabCut model - inputs :class:`tensorflow.Tensor` - Input tensor(s) for the model - """ - - graph = tf.Graph() - with graph.as_default(): - tf.import_graph_def(graph_def, name="DLC") - graph.finalize() - - return graph - - -def get_output_nodes(graph): - """ - Get the output node names from a graph - - Parameters - ----------- - graph :class:`tensorflow.Graph` - The graph of the DeepLabCut model - - Returns - -------- - output : list - the output node names as a list of strings - """ - - op_names = [str(op.name) for op in graph.get_operations()] - if "concat_1" in op_names[-1]: - output = [op_names[-1]] - else: - output = [op_names[-1], op_names[-2]] - - return output - - -def get_output_tensors(graph): - """ - Get the names of the output tensors from a graph - - Parameters - ----------- - graph :class:`tensorflow.Graph` - The graph of the DeepLabCut model - - Returns - -------- - output : list - the output tensor names as a list of strings - """ - - output_nodes = get_output_nodes(graph) - output_tensor = [out + ":0" for out in output_nodes] - return output_tensor - - -def get_input_tensor(graph): - input_tensor = str(graph.get_operations()[0].name) + ":0" - return input_tensor - - -def extract_graph( - graph, tf_config=None -) -> tuple[tf.Session, tf.Tensor, list[tf.Tensor]]: - """ - Initializes a tensorflow session with the specified graph and extracts the model's inputs and outputs - - Parameters - ----------- - graph :class:`tensorflow.Graph` - a tensorflow graph containing the desired model - tf_config :class:`tensorflow.ConfigProto` - - Returns - -------- - sess :class:`tensorflow.Session` - a tensorflow session with the specified graph definition - outputs :class:`tensorflow.Tensor` - the output tensor(s) for the model - """ - - input_tensor = get_input_tensor(graph) - output_tensor = get_output_tensors(graph) - sess = tf.Session(graph=graph, config=tf_config) - inputs = graph.get_tensor_by_name(input_tensor) - outputs = [graph.get_tensor_by_name(out) for out in output_tensor] - - return sess, inputs, outputs diff --git a/dlclive/pose.py b/dlclive/pose.py deleted file mode 100644 index 4cc80f8..0000000 --- a/dlclive/pose.py +++ /dev/null @@ -1,123 +0,0 @@ -""" -DeepLabCut Toolbox (deeplabcut.org) -© A. & M. Mathis Labs - -Licensed under GNU Lesser General Public License v3.0 -""" - -# NOTE DUPLICATED @C-Achard 2026-26-01: Duplication between this file -# and dlclive/pose_estimation_tensorflow/pose.py -# As this is tensorflow-specific and only the other pose.py is used, -# this one is candidate for deletion. -import numpy as np - - -def extract_cnn_output(outputs, cfg): - """ - Extract location refinement and score map from DeepLabCut network - - Parameters - ----------- - outputs : list - List of outputs from DeepLabCut network. - Requires 2 entries: - index 0 is output from Sigmoid - index 1 is output from pose/locref_pred/block4/BiasAdd - - cfg : dict - Dictionary read from the pose_cfg.yaml file for the network. - - Returns - -------- - scmap : ? - score map - - locref : ? - location refinement - """ - - scmap = outputs[0] - scmap = np.squeeze(scmap) - locref = None - if cfg["location_refinement"]: - locref = np.squeeze(outputs[1]) - shape = locref.shape - locref = np.reshape(locref, (shape[0], shape[1], -1, 2)) - locref *= cfg["locref_stdev"] - if len(scmap.shape) == 2: # for single body part! - scmap = np.expand_dims(scmap, axis=2) - return scmap, locref - - -def argmax_pose_predict(scmap, offmat, stride): - """ - Combines score map and offsets to the final pose - - Parameters - ----------- - scmap : ? - score map - - offmat : ? - offsets - - stride : ? - ? - - Returns - -------- - pose :class:`numpy.ndarray` - pose as a numpy array - """ - - num_joints = scmap.shape[2] - pose = [] - for joint_idx in range(num_joints): - maxloc = np.unravel_index( - np.argmax(scmap[:, :, joint_idx]), scmap[:, :, joint_idx].shape - ) - offset = np.array(offmat[maxloc][joint_idx])[::-1] - pos_f8 = np.array(maxloc).astype("float") * stride + 0.5 * stride + offset - pose.append(np.hstack((pos_f8[::-1], [scmap[maxloc][joint_idx]]))) - return np.array(pose) - - -def get_top_values(scmap, n_top=5): - batchsize, ny, nx, num_joints = scmap.shape - scmap_flat = scmap.reshape(batchsize, nx * ny, num_joints) - if n_top == 1: - scmap_top = np.argmax(scmap_flat, axis=1)[None] - else: - scmap_top = np.argpartition(scmap_flat, -n_top, axis=1)[:, -n_top:] - for ix in range(batchsize): - vals = scmap_flat[ix, scmap_top[ix], np.arange(num_joints)] - arg = np.argsort(-vals, axis=0) - scmap_top[ix] = scmap_top[ix, arg, np.arange(num_joints)] - scmap_top = scmap_top.swapaxes(0, 1) - - Y, X = np.unravel_index(scmap_top, (ny, nx)) - return Y, X - - -def multi_pose_predict(scmap, locref, stride, num_outputs): - Y, X = get_top_values(scmap[None], num_outputs) - Y, X = Y[:, 0], X[:, 0] - num_joints = scmap.shape[2] - DZ = np.zeros((num_outputs, num_joints, 3)) - for m in range(num_outputs): - for k in range(num_joints): - x = X[m, k] - y = Y[m, k] - DZ[m, k, :2] = locref[y, x, k, :] - DZ[m, k, 2] = scmap[y, x, k] - - X = X.astype("float32") * stride + 0.5 * stride + DZ[:, :, 0] - Y = Y.astype("float32") * stride + 0.5 * stride + DZ[:, :, 1] - P = DZ[:, :, 2] - - pose = np.empty((num_joints, num_outputs * 3), dtype="float32") - pose[:, 0::3] = X.T - pose[:, 1::3] = Y.T - pose[:, 2::3] = P.T - - return pose From 0d5e2c92df4a1790a44bab8ec8cd9fb852adb980 Mon Sep 17 00:00:00 2001 From: Cyril Achard Date: Wed, 28 Jan 2026 15:13:42 +0100 Subject: [PATCH 3/3] Remove duplication comments (reason: solved) Co-authored-by: Jaap de Ruyter van Steveninck <32810691+deruyter92@users.noreply.github.com> --- dlclive/pose_estimation_tensorflow/graph.py | 2 -- dlclive/pose_estimation_tensorflow/pose.py | 2 -- 2 files changed, 4 deletions(-) diff --git a/dlclive/pose_estimation_tensorflow/graph.py b/dlclive/pose_estimation_tensorflow/graph.py index 5f6b383..20c4203 100644 --- a/dlclive/pose_estimation_tensorflow/graph.py +++ b/dlclive/pose_estimation_tensorflow/graph.py @@ -5,8 +5,6 @@ Licensed under GNU Lesser General Public License v3.0 """ -# NOTE DUPLICATED @C-Achard 2026-26-01: Duplication between this file -# and dlclive/graph.py import tensorflow as tf vers = (tf.__version__).split(".") diff --git a/dlclive/pose_estimation_tensorflow/pose.py b/dlclive/pose_estimation_tensorflow/pose.py index b14ee67..b7f9cd7 100644 --- a/dlclive/pose_estimation_tensorflow/pose.py +++ b/dlclive/pose_estimation_tensorflow/pose.py @@ -5,8 +5,6 @@ Licensed under GNU Lesser General Public License v3.0 """ -# NOTE DUPLICATED @C-Achard 2026-26-01: Duplication between this file -# and dlclive/pose.py import numpy as np