#endif // OPENCV_HAVE_FILESYSTEM_SUPPORT
+
+struct OpenCLExecutionContext::Impl
+{
+ ocl::Context context_;
+ int device_; // device index in context
+ ocl::Queue queue_;
+ int useOpenCL_;
+
+protected:
+ Impl() = delete;
+
+ void _init_device(cl_device_id deviceID)
+ {
+ CV_Assert(deviceID);
+ int ndevices = (int)context_.ndevices();
+ CV_Assert(ndevices > 0);
+ bool found = false;
+ for (int i = 0; i < ndevices; i++)
+ {
+ ocl::Device d = context_.device(i);
+ cl_device_id dhandle = (cl_device_id)d.ptr();
+ if (dhandle == deviceID)
+ {
+ device_ = i;
+ found = true;
+ break;
+ }
+ }
+ CV_Assert(found && "OpenCL device can't work with passed OpenCL context");
+ }
+
+ void _init_device(const ocl::Device& device)
+ {
+ CV_Assert(device.ptr());
+ int ndevices = (int)context_.ndevices();
+ CV_Assert(ndevices > 0);
+ bool found = false;
+ for (int i = 0; i < ndevices; i++)
+ {
+ ocl::Device d = context_.device(i);
+ if (d.getImpl() == device.getImpl())
+ {
+ device_ = i;
+ found = true;
+ break;
+ }
+ }
+ CV_Assert(found && "OpenCL device can't work with passed OpenCL context");
+ }
+
+public:
+ Impl(cl_platform_id platformID, cl_context context, cl_device_id deviceID)
+ : device_(0), useOpenCL_(-1)
+ {
+ CV_UNUSED(platformID);
+ CV_Assert(context);
+ CV_Assert(deviceID);
+
+ context_ = Context::fromHandle(context);
+ _init_device(deviceID);
+ queue_ = Queue(context_, context_.device(device_));
+ }
+
+ Impl(const ocl::Context& context, const ocl::Device& device, const ocl::Queue& queue)
+ : device_(0), useOpenCL_(-1)
+ {
+ CV_Assert(context.ptr());
+ CV_Assert(device.ptr());
+
+ context_ = context;
+ _init_device(device);
+ queue_ = queue;
+ }
+
+ Impl(const ocl::Context& context, const ocl::Device& device)
+ : device_(0), useOpenCL_(-1)
+ {
+ CV_Assert(context.ptr());
+ CV_Assert(device.ptr());
+
+ context_ = context;
+ _init_device(device);
+ queue_ = Queue(context_, context_.device(device_));
+ }
+
+ Impl(const ocl::Context& context, const int device, const ocl::Queue& queue)
+ : context_(context)
+ , device_(device)
+ , queue_(queue)
+ , useOpenCL_(-1)
+ {
+ // nothing
+ }
+ Impl(const Impl& other)
+ : context_(other.context_)
+ , device_(other.device_)
+ , queue_(other.queue_)
+ , useOpenCL_(-1)
+ {
+ // nothing
+ }
+
+ inline bool useOpenCL() const { return const_cast<Impl*>(this)->useOpenCL(); }
+ bool useOpenCL()
+ {
+ if (useOpenCL_ < 0)
+ {
+ try
+ {
+ useOpenCL_ = 0;
+ if (!context_.empty() && context_.ndevices() > 0)
+ {
+ const Device& d = context_.device(device_);
+ useOpenCL_ = d.available();
+ }
+ }
+ catch (const cv::Exception&)
+ {
+ // nothing
+ }
+ if (!useOpenCL_)
+ CV_LOG_INFO(NULL, "OpenCL: can't use OpenCL execution context");
+ }
+ return useOpenCL_ > 0;
+ }
+
+ void setUseOpenCL(bool flag)
+ {
+ if (!flag)
+ useOpenCL_ = 0;
+ else
+ useOpenCL_ = -1;
+ }
+
+ static const std::shared_ptr<Impl>& getInitializedExecutionContext()
+ {
+ CV_TRACE_FUNCTION();
+
+ CV_LOG_INFO(NULL, "OpenCL: initializing thread execution context");
+
+ static bool initialized = false;
+ static std::shared_ptr<Impl> g_primaryExecutionContext;
+
+ if (!initialized)
+ {
+ cv::AutoLock lock(getInitializationMutex());
+ if (!initialized)
+ {
+ CV_LOG_INFO(NULL, "OpenCL: creating new execution context...");
+ try
+ {
+ Context c = ocl::Context::create(std::string());
+ if (c.ndevices())
+ {
+ int deviceId = 0;
+ auto& d = c.device(deviceId);
+ if (d.available())
+ {
+ auto q = ocl::Queue(c, d);
+ if (!q.ptr())
+ {
+ CV_LOG_ERROR(NULL, "OpenCL: Can't create default OpenCL queue");
+ }
+ else
+ {
+ g_primaryExecutionContext = std::make_shared<Impl>(c, deviceId, q);
+ CV_LOG_INFO(NULL, "OpenCL: device=" << d.name());
+ }
+ }
+ else
+ {
+ CV_LOG_ERROR(NULL, "OpenCL: OpenCL device is not available (CL_DEVICE_AVAILABLE returns false)");
+ }
+ }
+ else
+ {
+ CV_LOG_INFO(NULL, "OpenCL: context is not available/disabled");
+ }
+ }
+ catch (const std::exception& e)
+ {
+ CV_LOG_INFO(NULL, "OpenCL: Can't initialize OpenCL context/device/queue: " << e.what());
+ }
+ catch (...)
+ {
+ CV_LOG_WARNING(NULL, "OpenCL: Can't initialize OpenCL context/device/queue: unknown C++ exception");
+ }
+ initialized = true;
+ }
+ }
+ return g_primaryExecutionContext;
+ }
+};
+
+Context& OpenCLExecutionContext::getContext() const
+{
+ CV_Assert(p);
+ return p->context_;
+}
+Device& OpenCLExecutionContext::getDevice() const
+{
+ CV_Assert(p);
+ return p->context_.device(p->device_);
+}
+Queue& OpenCLExecutionContext::getQueue() const
+{
+ CV_Assert(p);
+ return p->queue_;
+}
+
+bool OpenCLExecutionContext::useOpenCL() const
+{
+ if (p)
+ return p->useOpenCL();
+ return false;
+}
+void OpenCLExecutionContext::setUseOpenCL(bool flag)
+{
+ CV_Assert(p);
+ p->setUseOpenCL(flag);
+}
+
+/* static */
+OpenCLExecutionContext& OpenCLExecutionContext::getCurrent()
+{
+ CV_TRACE_FUNCTION();
+ CoreTLSData& data = getCoreTlsData();
+ OpenCLExecutionContext& c = data.oclExecutionContext;
+ if (!data.oclExecutionContextInitialized)
+ {
+ data.oclExecutionContextInitialized = true;
+ if (c.empty() && haveOpenCL())
+ c.p = Impl::getInitializedExecutionContext();
+ }
+ return c;
+}
+
+/* static */
+OpenCLExecutionContext& OpenCLExecutionContext::getCurrentRef()
+{
+ CV_TRACE_FUNCTION();
+ CoreTLSData& data = getCoreTlsData();
+ OpenCLExecutionContext& c = data.oclExecutionContext;
+ return c;
+}
+
+void OpenCLExecutionContext::bind() const
+{
+ CV_TRACE_FUNCTION();
+ CV_Assert(p);
+ CoreTLSData& data = getCoreTlsData();
+ data.oclExecutionContext = *this;
+ data.oclExecutionContextInitialized = true;
+ data.useOpenCL = p->useOpenCL_; // propagate "-1", avoid call useOpenCL()
+}
+
+
+OpenCLExecutionContext OpenCLExecutionContext::cloneWithNewQueue() const
+{
+ CV_TRACE_FUNCTION();
+ CV_Assert(p);
+ const Queue q(getContext(), getDevice());
+ return cloneWithNewQueue(q);
+}
+
+OpenCLExecutionContext OpenCLExecutionContext::cloneWithNewQueue(const ocl::Queue& q) const
+{
+ CV_TRACE_FUNCTION();
+ CV_Assert(p);
+ CV_Assert(q.ptr() != NULL);
+ OpenCLExecutionContext c;
+ c.p = std::make_shared<Impl>(p->context_, p->device_, q);
+ return c;
+}
+
+/* static */
+OpenCLExecutionContext OpenCLExecutionContext::create(const Context& context, const Device& device, const ocl::Queue& queue)
+{
+ CV_TRACE_FUNCTION();
+ if (!haveOpenCL())
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL runtime is not available!");
+
+ CV_Assert(!context.empty());
+ CV_Assert(context.ptr());
+ CV_Assert(!device.empty());
+ CV_Assert(device.ptr());
+ OpenCLExecutionContext ctx;
+ ctx.p = std::make_shared<OpenCLExecutionContext::Impl>(context, device, queue);
+ return ctx;
+
+}
+
+/* static */
+OpenCLExecutionContext OpenCLExecutionContext::create(const Context& context, const Device& device)
+{
+ CV_TRACE_FUNCTION();
+ if (!haveOpenCL())
+ CV_Error(cv::Error::OpenCLApiCallError, "OpenCL runtime is not available!");
+
+ CV_Assert(!context.empty());
+ CV_Assert(context.ptr());
+ CV_Assert(!device.empty());
+ CV_Assert(device.ptr());
+ OpenCLExecutionContext ctx;
+ ctx.p = std::make_shared<OpenCLExecutionContext::Impl>(context, device);
+ return ctx;
+
+}
+
+void OpenCLExecutionContext::release()
+{
+ CV_TRACE_FUNCTION();
+ p.reset();
+}
+
+
++
// true if we have initialized OpenCL subsystem with available platforms
- static bool g_isOpenCLActivated = false;
+ static bool g_isOpenCLInitialized = false;
+ static bool g_isOpenCLAvailable = false;
bool haveOpenCL()
{
{
cl_uint n = 0;
g_isOpenCLAvailable = ::clGetPlatformIDs(0, NULL, &n) == CL_SUCCESS;
- g_isOpenCLActivated = n > 0;
+ g_isOpenCLAvailable &= n > 0;
+ CV_LOG_INFO(NULL, "OpenCL: found " << n << " platforms");
}
catch (...)
{
normAssert(self, blob, target)
- # FIXIT never properly work: cv.rectangle(frame, list(box), (0, 255, 0))
+ def test_model(self):
+ img_path = self.find_dnn_file("dnn/street.png")
+ weights = self.find_dnn_file("dnn/MobileNetSSD_deploy.caffemodel", required=False)
+ config = self.find_dnn_file("dnn/MobileNetSSD_deploy.prototxt", required=False)
+ if weights is None or config is None:
+ raise unittest.SkipTest("Missing DNN test files (dnn/MobileNetSSD_deploy.{prototxt/caffemodel}). Verify OPENCV_DNN_TEST_DATA_PATH configuration parameter.")
+
+ frame = cv.imread(img_path)
+ model = cv.dnn_DetectionModel(weights, config)
+ model.setInputParams(size=(300, 300), mean=(127.5, 127.5, 127.5), scale=1.0/127.5)
+
+ iouDiff = 0.05
+ confThreshold = 0.0001
+ nmsThreshold = 0
+ scoreDiff = 1e-3
+
+ classIds, confidences, boxes = model.detect(frame, confThreshold, nmsThreshold)
+
+ refClassIds = (7, 15)
+ refConfidences = (0.9998, 0.8793)
+ refBoxes = ((328, 238, 85, 102), (101, 188, 34, 138))
+
+ normAssertDetections(self, refClassIds, refConfidences, refBoxes,
+ classIds, confidences, boxes,confThreshold, scoreDiff, iouDiff)
+
+ for box in boxes:
+ cv.rectangle(frame, box, (0, 255, 0))
+ cv.rectangle(frame, np.array(box), (0, 255, 0))
+ cv.rectangle(frame, tuple(box), (0, 255, 0))
++ cv.rectangle(frame, list(box), (0, 255, 0))
+
+
+ def test_classification_model(self):
+ img_path = self.find_dnn_file("dnn/googlenet_0.png")
+ weights = self.find_dnn_file("dnn/squeezenet_v1.1.caffemodel", required=False)
+ config = self.find_dnn_file("dnn/squeezenet_v1.1.prototxt")
+ ref = np.load(self.find_dnn_file("dnn/squeezenet_v1.1_prob.npy"))
+ if weights is None or config is None:
+ raise unittest.SkipTest("Missing DNN test files (dnn/squeezenet_v1.1.{prototxt/caffemodel}). Verify OPENCV_DNN_TEST_DATA_PATH configuration parameter.")
+
+ frame = cv.imread(img_path)
+ model = cv.dnn_ClassificationModel(config, weights)
+ model.setInputSize(227, 227)
+ model.setInputCrop(True)
+
+ out = model.predict(frame)
+ normAssert(self, out, ref)
+
+
def test_face_detection(self):
proto = self.find_dnn_file('dnn/opencv_face_detector.prototxt')
model = self.find_dnn_file('dnn/opencv_face_detector.caffemodel', required=False)