Mercurial > hg > orthanc-stone
comparison Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp @ 1950:6ffd65cfd2ee deep-learning
new branch: deep-learning
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 12 Aug 2022 15:48:35 +0200 |
parents | d459477804bf |
children | 060d61913e39 |
comparison
equal
deleted
inserted
replaced
1949:d3ae6858e77b | 1950:6ffd65cfd2ee |
---|---|
2279 if (cursor_.get() != NULL && | 2279 if (cursor_.get() != NULL && |
2280 frames_.get() != NULL) | 2280 frames_.get() != NULL) |
2281 { | 2281 { |
2282 const size_t cursorIndex = cursor_->GetCurrentIndex(); | 2282 const size_t cursorIndex = cursor_->GetCurrentIndex(); |
2283 const OrthancStone::DicomInstanceParameters& instance = frames_->GetInstanceOfFrame(cursorIndex); | 2283 const OrthancStone::DicomInstanceParameters& instance = frames_->GetInstanceOfFrame(cursorIndex); |
2284 const size_t frameNumber = frames_->GetFrameNumberInInstance(cursorIndex); | 2284 const unsigned int frameNumber = frames_->GetFrameNumberInInstance(cursorIndex); |
2285 | 2285 |
2286 // Only change the scene if the loaded frame still corresponds to the current cursor | 2286 // Only change the scene if the loaded frame still corresponds to the current cursor |
2287 if (instance.GetSopInstanceUid() == loadedSopInstanceUid && | 2287 if (instance.GetSopInstanceUid() == loadedSopInstanceUid && |
2288 frameNumber == loadedFrameNumber) | 2288 frameNumber == loadedFrameNumber) |
2289 { | 2289 { |
2603 if (cursor_.get() != NULL && | 2603 if (cursor_.get() != NULL && |
2604 frames_.get() != NULL) | 2604 frames_.get() != NULL) |
2605 { | 2605 { |
2606 const size_t cursorIndex = cursor_->GetCurrentIndex(); | 2606 const size_t cursorIndex = cursor_->GetCurrentIndex(); |
2607 const OrthancStone::DicomInstanceParameters& instance = frames_->GetInstanceOfFrame(cursorIndex); | 2607 const OrthancStone::DicomInstanceParameters& instance = frames_->GetInstanceOfFrame(cursorIndex); |
2608 const size_t frameNumber = frames_->GetFrameNumberInInstance(cursorIndex); | 2608 const unsigned int frameNumber = frames_->GetFrameNumberInInstance(cursorIndex); |
2609 | 2609 |
2610 StoneAnnotationsRegistry::GetInstance().Save(instance.GetSopInstanceUid(), frameNumber, *stoneAnnotations_); | 2610 StoneAnnotationsRegistry::GetInstance().Save(instance.GetSopInstanceUid(), frameNumber, *stoneAnnotations_); |
2611 | 2611 |
2612 if (observer_.get() != NULL) | 2612 if (observer_.get() != NULL) |
2613 { | 2613 { |
2798 frames_.get() != NULL) | 2798 frames_.get() != NULL) |
2799 { | 2799 { |
2800 const size_t cursorIndex = cursor_->GetCurrentIndex(); | 2800 const size_t cursorIndex = cursor_->GetCurrentIndex(); |
2801 | 2801 |
2802 const OrthancStone::DicomInstanceParameters& instance = frames_->GetInstanceOfFrame(cursorIndex); | 2802 const OrthancStone::DicomInstanceParameters& instance = frames_->GetInstanceOfFrame(cursorIndex); |
2803 const size_t frameNumber = frames_->GetFrameNumberInInstance(cursorIndex); | 2803 const unsigned int frameNumber = frames_->GetFrameNumberInInstance(cursorIndex); |
2804 | 2804 |
2805 FramesCache::Accessor accessor(*framesCache_, instance.GetSopInstanceUid(), frameNumber); | 2805 FramesCache::Accessor accessor(*framesCache_, instance.GetSopInstanceUid(), frameNumber); |
2806 if (accessor.IsValid()) | 2806 if (accessor.IsValid()) |
2807 { | 2807 { |
2808 RenderCurrentScene(accessor.GetImage(), instance, frameNumber, frames_->GetFrameGeometry(cursorIndex)); | 2808 RenderCurrentScene(accessor.GetImage(), instance, frameNumber, frames_->GetFrameGeometry(cursorIndex)); |
3300 if (cursor_.get() != NULL && | 3300 if (cursor_.get() != NULL && |
3301 frames_.get() != NULL) | 3301 frames_.get() != NULL) |
3302 { | 3302 { |
3303 const size_t cursorIndex = cursor_->GetCurrentIndex(); | 3303 const size_t cursorIndex = cursor_->GetCurrentIndex(); |
3304 const OrthancStone::DicomInstanceParameters& instance = frames_->GetInstanceOfFrame(cursorIndex); | 3304 const OrthancStone::DicomInstanceParameters& instance = frames_->GetInstanceOfFrame(cursorIndex); |
3305 const size_t frameNumber = frames_->GetFrameNumberInInstance(cursorIndex); | 3305 const unsigned int frameNumber = frames_->GetFrameNumberInInstance(cursorIndex); |
3306 | 3306 |
3307 if (instance.GetSopInstanceUid() == sopInstanceUid && | 3307 if (instance.GetSopInstanceUid() == sopInstanceUid && |
3308 frameNumber == frame) | 3308 frameNumber == frame) |
3309 { | 3309 { |
3310 StoneAnnotationsRegistry::GetInstance().Load(*stoneAnnotations_, instance.GetSopInstanceUid(), frame); | 3310 StoneAnnotationsRegistry::GetInstance().Load(*stoneAnnotations_, instance.GetSopInstanceUid(), frame); |
3314 stoneAnnotations_->Render(lock->GetController().GetScene()); | 3314 stoneAnnotations_->Render(lock->GetController().GetScene()); |
3315 lock->Invalidate(); | 3315 lock->Invalidate(); |
3316 } | 3316 } |
3317 } | 3317 } |
3318 } | 3318 } |
3319 } | |
3320 | |
3321 | |
3322 bool GetCurrentFrame(std::string& sopInstanceUid, | |
3323 unsigned int& frameNumber) const | |
3324 { | |
3325 if (cursor_.get() != NULL && | |
3326 frames_.get() != NULL) | |
3327 { | |
3328 const size_t cursorIndex = cursor_->GetCurrentIndex(); | |
3329 const OrthancStone::DicomInstanceParameters& instance = frames_->GetInstanceOfFrame(cursorIndex); | |
3330 sopInstanceUid = instance.GetSopInstanceUid(); | |
3331 frameNumber = frames_->GetFrameNumberInInstance(cursorIndex); | |
3332 return true; | |
3333 } | |
3334 else | |
3335 { | |
3336 return false; | |
3337 } | |
3319 } | 3338 } |
3320 }; | 3339 }; |
3321 | 3340 |
3322 | 3341 |
3323 | 3342 |
3644 return found->second; | 3663 return found->second; |
3645 } | 3664 } |
3646 } | 3665 } |
3647 | 3666 |
3648 | 3667 |
3668 #include <emscripten/fetch.h> | |
3669 #include "deep-learning/WebAssembly/Worker.pb.h" | |
3670 | |
3671 static void DeepLearningCallback(char* data, | |
3672 int size, | |
3673 void* payload) | |
3674 { | |
3675 OrthancStone::Messages::Response response; | |
3676 if (response.ParseFromArray(data, size)) | |
3677 { | |
3678 switch (response.type()) | |
3679 { | |
3680 case OrthancStone::Messages::ResponseType::INITIALIZED: | |
3681 DISPATCH_JAVASCRIPT_EVENT("DeepLearningInitialized"); | |
3682 break; | |
3683 | |
3684 case OrthancStone::Messages::ResponseType::PARSED_MODEL: | |
3685 LOG(WARNING) << "Number of steps in the model: " << response.parse_model().number_of_steps(); | |
3686 DISPATCH_JAVASCRIPT_EVENT("DeepLearningReady"); | |
3687 break; | |
3688 | |
3689 default: | |
3690 LOG(ERROR) << "Unsupported response type from the deep learning worker"; | |
3691 } | |
3692 } | |
3693 else | |
3694 { | |
3695 LOG(ERROR) << "Bad response received from the deep learning worker"; | |
3696 } | |
3697 } | |
3698 | |
3699 static worker_handle deepLearningWorker_; | |
3700 | |
3701 static void SendRequestToWebWorker(const OrthancStone::Messages::Request& request) | |
3702 { | |
3703 std::string s; | |
3704 if (request.SerializeToString(&s) && | |
3705 !s.empty()) | |
3706 { | |
3707 emscripten_call_worker(deepLearningWorker_, "Execute", &s[0], s.size(), DeepLearningCallback, NULL); | |
3708 } | |
3709 else | |
3710 { | |
3711 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, | |
3712 "Cannot send command to the Web worker"); | |
3713 } | |
3714 } | |
3715 | |
3716 static void DeepLearningModelLoaded(emscripten_fetch_t *fetch) | |
3717 { | |
3718 try | |
3719 { | |
3720 LOG(WARNING) << "Deep learning model loaded: " << fetch->numBytes; | |
3721 | |
3722 OrthancStone::Messages::Request request; | |
3723 request.set_type(OrthancStone::Messages::RequestType::PARSE_MODEL); | |
3724 request.mutable_parse_model()->mutable_content()->assign(fetch->data, fetch->numBytes); | |
3725 | |
3726 emscripten_fetch_close(fetch); // Don't use "fetch" below | |
3727 SendRequestToWebWorker(request); | |
3728 } | |
3729 EXTERN_CATCH_EXCEPTIONS; | |
3730 } | |
3731 | |
3649 extern "C" | 3732 extern "C" |
3650 { | 3733 { |
3651 int main(int argc, char const *argv[]) | 3734 int main(int argc, char const *argv[]) |
3652 { | 3735 { |
3653 printf("Initializing Stone\n"); | 3736 printf("Initializing Stone\n"); |
3659 context_->SetDicomCacheSize(128 * 1024 * 1024); // 128MB | 3742 context_->SetDicomCacheSize(128 * 1024 * 1024); // 128MB |
3660 | 3743 |
3661 framesCache_.reset(new FramesCache); | 3744 framesCache_.reset(new FramesCache); |
3662 osiriXAnnotations_.reset(new OrthancStone::OsiriX::CollectionOfAnnotations); | 3745 osiriXAnnotations_.reset(new OrthancStone::OsiriX::CollectionOfAnnotations); |
3663 | 3746 |
3747 deepLearningWorker_ = emscripten_create_worker("DeepLearningWorker.js"); | |
3748 emscripten_call_worker(deepLearningWorker_, "Initialize", NULL, 0, DeepLearningCallback, NULL); | |
3749 | |
3664 DISPATCH_JAVASCRIPT_EVENT("StoneInitialized"); | 3750 DISPATCH_JAVASCRIPT_EVENT("StoneInitialized"); |
3751 } | |
3752 | |
3753 | |
3754 EMSCRIPTEN_KEEPALIVE | |
3755 void LoadDeepLearningModel(const char* uri) | |
3756 { | |
3757 try | |
3758 { | |
3759 LOG(WARNING) << "Loading deep learning model: " << uri; | |
3760 | |
3761 emscripten_fetch_attr_t attr; | |
3762 emscripten_fetch_attr_init(&attr); | |
3763 strcpy(attr.requestMethod, "GET"); | |
3764 attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY; | |
3765 attr.onsuccess = DeepLearningModelLoaded; | |
3766 attr.onerror = NULL; | |
3767 emscripten_fetch(&attr, uri); | |
3768 } | |
3769 EXTERN_CATCH_EXCEPTIONS; | |
3770 } | |
3771 | |
3772 | |
3773 EMSCRIPTEN_KEEPALIVE | |
3774 void ApplyDeepLearningModel(const char* canvas) | |
3775 { | |
3776 try | |
3777 { | |
3778 boost::shared_ptr<ViewerViewport> viewport = GetViewport(canvas); | |
3779 | |
3780 std::string sopInstanceUid; | |
3781 unsigned int frameNumber; | |
3782 if (viewport->GetCurrentFrame(sopInstanceUid, frameNumber)) | |
3783 { | |
3784 LOG(ERROR) << "OK: " << sopInstanceUid << " / " << frameNumber; | |
3785 | |
3786 FramesCache::Accessor accessor(*framesCache_, sopInstanceUid, frameNumber); | |
3787 if (accessor.IsValid() && | |
3788 accessor.GetImage().GetFormat() == Orthanc::PixelFormat_Float32) | |
3789 { | |
3790 const Orthanc::ImageAccessor& image = accessor.GetImage(); | |
3791 | |
3792 OrthancStone::Messages::Request request; | |
3793 request.set_type(OrthancStone::Messages::RequestType::LOAD_IMAGE); | |
3794 request.mutable_load_image()->set_sop_instance_uid(sopInstanceUid); | |
3795 request.mutable_load_image()->set_frame_number(frameNumber); | |
3796 request.mutable_load_image()->set_width(image.GetWidth()); | |
3797 request.mutable_load_image()->set_height(image.GetHeight()); | |
3798 | |
3799 const unsigned int height = image.GetHeight(); | |
3800 const unsigned int width = image.GetWidth(); | |
3801 for (unsigned int y = 0; y < height; y++) | |
3802 { | |
3803 const float* p = reinterpret_cast<const float*>(image.GetConstRow(y)); | |
3804 for (unsigned int x = 0; x < width; x++, p++) | |
3805 { | |
3806 request.mutable_load_image()->mutable_values()->Add(*p); | |
3807 } | |
3808 } | |
3809 | |
3810 SendRequestToWebWorker(request); | |
3811 } | |
3812 else | |
3813 { | |
3814 LOG(WARNING) << "Cannot access graylevel frame"; | |
3815 } | |
3816 } | |
3817 else | |
3818 { | |
3819 LOG(WARNING) << "No active frame"; | |
3820 } | |
3821 } | |
3822 EXTERN_CATCH_EXCEPTIONS; | |
3665 } | 3823 } |
3666 | 3824 |
3667 | 3825 |
3668 EMSCRIPTEN_KEEPALIVE | 3826 EMSCRIPTEN_KEEPALIVE |
3669 void SetDicomWebRoot(const char* uri, | 3827 void SetDicomWebRoot(const char* uri, |