1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 15:53:03 +04:00

Merge pull request #28678 from omrope79:caffe-importer-cleanup

Caffe importer cleanup #28678

Merge with: https://github.com/opencv/opencv_extra/pull/1324

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [x] There is a reference to the original bug report and related work
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
- [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
omrope79
2026-06-02 19:58:10 +05:30
committed by GitHub
parent 42fc6939f8
commit b67ad9a422
34 changed files with 327 additions and 5674 deletions
@@ -1,24 +1,20 @@
set(sample example-mobilenet-objdetect)
ocv_download(FILENAME "mobilenet_iter_73000.caffemodel"
HASH "bbcb3b6a0afe1ec89e1288096b5b8c66"
URL
"${OPENCV_MOBILENET_SSD_WEIGHTS_URL}"
"$ENV{OPENCV_MOBILENET_SSD_WEIGHTS_URL}"
"https://raw.githubusercontent.com/chuanqi305/MobileNet-SSD/97406996b1eee2d40eb0a00ae567cf41e23369f9/mobilenet_iter_73000.caffemodel"
DESTINATION_DIR "${CMAKE_CURRENT_LIST_DIR}/res/raw"
ID OPENCV_MOBILENET_SSD_WEIGHTS
STATUS res)
# Explicitly ensure resource directories exist to guarantee smooth resource compiling
file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/res/raw")
ocv_download(FILENAME "deploy.prototxt"
HASH "f1978dc4fe20c680e850ce99830c5945"
URL
"${OPENCV_MOBILENET_SSD_CONFIG_URL}"
"$ENV{OPENCV_MOBILENET_SSD_CONFIG_URL}"
"https://raw.githubusercontent.com/chuanqi305/MobileNet-SSD/97406996b1eee2d40eb0a00ae567cf41e23369f9/deploy.prototxt"
DESTINATION_DIR "${CMAKE_CURRENT_LIST_DIR}/res/raw"
ID OPENCV_MOBILENET_SSD_CONFIG
STATUS res)
# The Caffe MobileNet-SSD (mobilenet_iter_73000.caffemodel + deploy.prototxt) has been
# replaced by a single-file ONNX model. The sample now loads "res/raw/mobilenet.onnx".
if((DEFINED ENV{OPENCV_MOBILENET_SSD_ONNX_URL} OR DEFINED OPENCV_MOBILENET_SSD_ONNX_URL) AND OPENCV_MOBILENET_SSD_ONNX_HASH)
ocv_download(FILENAME "mobilenet.onnx"
HASH "${OPENCV_MOBILENET_SSD_ONNX_HASH}"
URL
"${OPENCV_MOBILENET_SSD_ONNX_URL}"
"$ENV{OPENCV_MOBILENET_SSD_ONNX_URL}"
DESTINATION_DIR "${CMAKE_CURRENT_SOURCE_DIR}/res/raw"
ID OPENCV_MOBILENET_SSD_ONNX
STATUS res)
endif()
add_android_project(${sample} "${CMAKE_CURRENT_SOURCE_DIR}" LIBRARY_DEPS "${OPENCV_ANDROID_LIB_DIR}" SDK_TARGET 11 "${ANDROID_SDK_TARGET}")
if(TARGET ${sample})
@@ -54,15 +54,19 @@ public class MainActivity extends CameraActivity implements CvCameraViewListener
}
//! [init_model_from_memory]
mModelBuffer = loadFileFromResource(R.raw.mobilenet_iter_73000);
mConfigBuffer = loadFileFromResource(R.raw.deploy);
if (mModelBuffer == null || mConfigBuffer == null) {
Log.e(TAG, "Failed to load model from resources");
} else
Log.i(TAG, "Model files loaded successfully");
// Load a single-file MobileNet-SSD ONNX model from res/raw/mobilenet.onnx.
// The resource is resolved by name at runtime so the sample still builds when the
// (optionally downloaded) model is absent; object detection is simply disabled then.
int modelResId = getResources().getIdentifier("mobilenet", "raw", getPackageName());
if (modelResId != 0)
mModelBuffer = loadFileFromResource(modelResId);
net = Dnn.readNet("caffe", mModelBuffer, mConfigBuffer);
Log.i(TAG, "Network loaded successfully");
if (mModelBuffer == null) {
Log.e(TAG, "MobileNet ONNX model (res/raw/mobilenet.onnx) not found - object detection disabled");
} else {
net = Dnn.readNetFromONNX(mModelBuffer);
Log.i(TAG, "Network loaded successfully");
}
//! [init_model_from_memory]
setContentView(R.layout.activity_main);
@@ -91,8 +95,8 @@ public class MainActivity extends CameraActivity implements CvCameraViewListener
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
mModelBuffer.release();
mConfigBuffer.release();
if (mModelBuffer != null)
mModelBuffer.release();
}
// Load a network.
@@ -107,7 +111,10 @@ public class MainActivity extends CameraActivity implements CvCameraViewListener
final double MEAN_VAL = 127.5;
final double THRESHOLD = 0.2;
// Get a new frame
if (net == null) {
return inputFrame.rgba();
}
Log.d(TAG, "handle new frame!");
Mat frame = inputFrame.rgba();
Imgproc.cvtColor(frame, frame, Imgproc.COLOR_RGBA2RGB);
@@ -188,7 +195,6 @@ public class MainActivity extends CameraActivity implements CvCameraViewListener
"motorbike", "person", "pottedplant",
"sheep", "sofa", "train", "tvmonitor"};
private MatOfByte mConfigBuffer;
private MatOfByte mModelBuffer;
private Net net;
private CameraBridgeViewBase mOpenCvCameraView;
+8 -37
View File
@@ -1,19 +1,14 @@
#!/usr/bin/env python
'''
This sample using FlowNet v2 and RAFT model to calculate optical flow.
FlowNet v2 Original Paper: https://arxiv.org/abs/1612.01925.
FlowNet v2 Repo: https://github.com/lmb-freiburg/flownet2.
Download the converted .caffemodel model from https://drive.google.com/open?id=16qvE9VNmU39NttpZwZs81Ga8VYQJDaWZ
and .prototxt from https://drive.google.com/file/d/1RyNIUsan1ZOh2hpYIH36A-jofAvJlT6a/view?usp=sharing.
Otherwise download original model from https://lmb.informatik.uni-freiburg.de/resources/binaries/flownet2/flownet2-models.tar.gz,
convert .h5 model to .caffemodel and modify original .prototxt using .prototxt from link above.
This sample uses the RAFT model to calculate optical flow.
RAFT Original Paper: https://arxiv.org/pdf/2003.12039.pdf
RAFT Repo: https://github.com/princeton-vl/RAFT
Download the .onnx model from here https://github.com/opencv/opencv_zoo/raw/281d232cd99cd920853106d853c440edd35eb442/models/optical_flow_estimation_raft/optical_flow_estimation_raft_2023aug.onnx.
Note: the legacy FlowNet v2 Caffe pipeline (--proto/.caffemodel) has been removed together
with the Caffe importer. Please provide a single ONNX model.
'''
import argparse
@@ -25,9 +20,8 @@ import cv2 as cv
class OpticalFlow(object):
def __init__(self, model, height, width, proto=""):
if proto:
self.net = cv.dnn.readNetFromCaffe(proto, model)
else:
self.net = cv.dnn.readNet(model)
raise cv.error("Caffe support has been removed. Please provide a single ONNX model path (e.g. RAFT).")
self.net = cv.dnn.readNet(model)
self.net.setPreferableBackend(cv.dnn.DNN_BACKEND_OPENCV)
self.height = height
self.width = width
@@ -75,41 +69,18 @@ if __name__ == '__main__':
parser.add_argument('-input', '-i', required=True, help='Path to input video file. Skip this argument to capture frames from a camera.')
parser.add_argument('--height', default=320, type=int, help='Input height')
parser.add_argument('--width', default=448, type=int, help='Input width')
parser.add_argument('--proto', '-p', default='', help='Path to prototxt.')
parser.add_argument('--model', '-m', required=True, help='Path to model.')
parser.add_argument('--model', '-m', required=True, help='Path to a single ONNX model (e.g. RAFT).')
args, _ = parser.parse_known_args()
if not os.path.isfile(args.model):
raise OSError("Model does not exist")
if args.proto and not os.path.isfile(args.proto):
raise OSError("Prototxt does not exist")
winName = 'Calculation optical flow in OpenCV'
cv.namedWindow(winName, cv.WINDOW_NORMAL)
cap = cv.VideoCapture(args.input if args.input else 0)
hasFrame, first_frame = cap.read()
if args.proto:
divisor = 64.
var = {}
var['ADAPTED_WIDTH'] = int(np.ceil(args.width/divisor) * divisor)
var['ADAPTED_HEIGHT'] = int(np.ceil(args.height/divisor) * divisor)
var['SCALE_WIDTH'] = args.width / float(var['ADAPTED_WIDTH'])
var['SCALE_HEIGHT'] = args.height / float(var['ADAPTED_HEIGHT'])
config = ''
proto = open(args.proto).readlines()
for line in proto:
for key, value in var.items():
tag = "$%s$" % key
line = line.replace(tag, str(value))
config += line
caffemodel = open(args.model, 'rb').read()
opt_flow = OpticalFlow(caffemodel, var['ADAPTED_HEIGHT'], var['ADAPTED_WIDTH'], bytearray(config.encode()))
else:
opt_flow = OpticalFlow(args.model, 360, 480)
opt_flow = OpticalFlow(args.model, 360, 480)
while cv.waitKey(1) < 0:
hasFrame, second_frame = cap.read()