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,