Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
!/plugins/**
!/ScopeOneCuda/
!/ScopeOneCuda/**
!/ScopeOneInference/
!/ScopeOneInference/**
/ScopeOneCore/install/
/ScopeOneCore/build/
/ScopeOneCore/external/*
Expand Down
19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,32 @@

<p align="center">
<a href="https://github.com/Experimental-Microscopy-Lab/ScopeOne/actions/workflows/compile-check.yml"><img src="https://github.com/Experimental-Microscopy-Lab/ScopeOne/actions/workflows/compile-check.yml/badge.svg?branch=main" alt="Compile Check"></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-BSD--3--Clause-blue.svg" alt="BSD 3-Clause License"></a>
<!-- <a href="https://doi.org/10.48550/arXiv.2606.19384"><img src="https://img.shields.io/badge/arXiv-2606.19384-b31b1b.svg" alt="Preprint DOI"></a> -->
</p>

ScopeOne is open-source microscopy control software built with C++ and Qt. Hardware is accessed through provider-independent device contracts; [Micro-Manager](https://micro-manager.org/) is the built-in provider, and isolated devices run through ScopeOne DriverHost processes.
It retains compatibility with the Micro-Manager device ecosystem while allowing native vendor providers and adds a modular real-time image processing pipeline with support for background calibration, temporal filtering, FFT analysis, and more.

ScopeOne is a high-performance open-source microscopy control platform built with C++ and Qt. It is designed to be an extensible platform for advanced microscopy applications, including multiple camera live imaging, on-the-fly image processing, and automated experiments.
It retains compatibility with the [Micro-Manager](https://micro-manager.org/) broad device ecosystem while allowing featuers like online image processing with GPU acceleration, deep learning inference and more.
<p align="center">
<img src="resources/Screenshot 2026-09-01 140040.png" width="720"><br>
<sub> Graphical User Interface of ScopeOne</sub>
</p>

As an open-source project, ScopeOne builds on existing community efforts to reduce duplicated work and provides an alternative that enriches the microscopy community. While the current development is conducted in close collaboration with the optics and biology teams within our laboratory, we aim to expand engagement with the broader research community to make the platform more practical, accessible, and universal. Any issues or pull requests are greatly appreciated!

## ✨ New Features

### Deep Learning Inference

Deep learning is becoming an increasingly powerful tool for microscopy image restoration and analysis. ScopeOne allows users to import pre-trained AI models through the widely supported ONNX model format and apply them directly to live camera streams or recorded images. Models can run on either the CPU or GPU.

<p align="center">
<img src="resources/ONNX.png" width="720"><br>
<sub>Real-time denoising demo using <a href="https://huggingface.co/qualcomm/DnCNN">DnCNN</a> at approximately 150 FPS for 256 × 256 images, tested on an NVIDIA RTX 4070 Ti</sub>
</p>

### GPU-Accelerated Online Image Processing
Despite the deep learning, traditional image processing methods remain essential. GPU-accelerated image processing pipeline can be applied to live camera streams or recorded images, including filtering, background subtraction, FFT, and more. Users can customize image processing algorithms and parameters to suit their specific needs via the ScopeOne plugin system.
## 🚀 Quick Start

### For Users
Expand Down
4 changes: 3 additions & 1 deletion ScopeOneCore/include/scopeone/ProcessingPlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ namespace scopeone::core
Integer,
Real,
Boolean,
Choice
Choice,
FilePath
};

struct ProcessingParameterChoice
Expand All @@ -39,6 +40,7 @@ namespace scopeone::core
QVariant step;
int decimals{0};
QList<ProcessingParameterChoice> choices;
QString fileFilter;
};

struct ProcessingModuleDescriptor
Expand Down
9 changes: 8 additions & 1 deletion ScopeOneCore/include/scopeone/SimulatorProvider.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#pragma once

#include <QByteArray>
#include <QObject>
#include <QMutex>
#include <QRect>
#include <QTimer>
#include <random>

#include "scopeone/CameraProvider.h"
#include "scopeone/HardwareProvider.h"
Expand Down Expand Up @@ -64,11 +66,13 @@ namespace scopeone::core
enum class ImageMode
{
Gradient,
Hologram
Hologram,
Beads
};

bool accepts(const QString& cameraIdOrAll) const;
ImageFrame makeFrame();
void rebuildBeadsImage();
void updateTimerInterval();

QString m_providerId;
Expand All @@ -77,8 +81,11 @@ namespace scopeone::core
int m_sensorHeight{512};
QRect m_roi;
double m_exposureMs{10.0};
double m_gaussianNoiseSigma{0.0};
ImageMode m_imageMode{ImageMode::Gradient};
QByteArray m_beadsImage;
quint64 m_frameIndex{0};
std::mt19937 m_randomGenerator{std::random_device{}()};
FrameSink m_frameSink;
PreviewStateSink m_previewStateSink;
QTimer m_timer;
Expand Down
21 changes: 12 additions & 9 deletions ScopeOneCore/src/ScopeOneCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -998,8 +998,8 @@ namespace scopeone::core
CameraManager* cameraManager{nullptr};
RecordingManager* recordingManager{nullptr};
ImageProcessingManager* imageProcessingManager{nullptr};
std::vector<std::unique_ptr<QLibrary>> processingExtensionLibraries;
std::unique_ptr<internal::ProcessingModuleRegistry> processingModuleRegistry;
std::unique_ptr<QLibrary> cudaLibrary;
StageMosaicManager* stageMosaicManager{nullptr};
internal::DaqDeviceManager* daqDeviceManager{nullptr};
internal::SignalSourceManager* signalSourceManager{nullptr};
Expand Down Expand Up @@ -1255,24 +1255,27 @@ namespace scopeone::core
"scopeone::core::ScanImageConfig");
m_managers->processingModuleRegistry =
std::make_unique<internal::ProcessingModuleRegistry>();
const QString cudaLibraryPath = QDir(QCoreApplication::applicationDirPath())
.filePath(QStringLiteral("ScopeOneCuda"));
{
auto cudaLibrary = std::make_unique<QLibrary>(cudaLibraryPath);
if (cudaLibrary->load())
const QStringList processingExtensionNames{
QStringLiteral("ScopeOneCuda"),
QStringLiteral("ScopeOneInference")};
for (const QString& extensionName : processingExtensionNames)
{
auto library = std::make_unique<QLibrary>(
QDir(QCoreApplication::applicationDirPath()).filePath(extensionName));
if (library->load())
{
using RegisterProcessingModules = void (*)(ScopeOneCore*);
const auto registerProcessingModules =
reinterpret_cast<RegisterProcessingModules>(
cudaLibrary->resolve("scopeone_register_processing_modules"));
library->resolve("scopeone_register_processing_modules"));
if (registerProcessingModules)
{
registerProcessingModules(this);
m_managers->cudaLibrary = std::move(cudaLibrary);
m_managers->processingExtensionLibraries.push_back(std::move(library));
}
else
{
cudaLibrary->unload();
library->unload();
}
}
}
Expand Down
Loading
Loading