comparison Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp @ 1953:0661115af939 deep-learning

first successful application of deep learning
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 16 Aug 2022 15:05:51 +0200
parents a1e0aae9c17f
children 2034ae383cfd
comparison
equal deleted inserted replaced
1952:a1e0aae9c17f 1953:0661115af939
1583 virtual void SignalStoneAnnotationRemoved(const ViewerViewport& viewport) = 0; 1583 virtual void SignalStoneAnnotationRemoved(const ViewerViewport& viewport) = 0;
1584 }; 1584 };
1585 1585
1586 private: 1586 private:
1587 static const int LAYER_TEXTURE = 0; 1587 static const int LAYER_TEXTURE = 0;
1588 static const int LAYER_OVERLAY = 1; 1588 static const int LAYER_DEEP_LEARNING = 1;
1589 static const int LAYER_REFERENCE_LINES = 2; 1589 static const int LAYER_OVERLAY = 2;
1590 static const int LAYER_ANNOTATIONS_OSIRIX = 3; 1590 static const int LAYER_REFERENCE_LINES = 3;
1591 static const int LAYER_ANNOTATIONS_STONE = 4; 1591 static const int LAYER_ANNOTATIONS_OSIRIX = 4;
1592 static const int LAYER_ANNOTATIONS_STONE = 5;
1592 1593
1593 1594
1594 class ICommand : public Orthanc::IDynamicObject 1595 class ICommand : public Orthanc::IDynamicObject
1595 { 1596 {
1596 private: 1597 private:
2005 // The coordinates of Stone annotations are expressed in 2D 2006 // The coordinates of Stone annotations are expressed in 2D
2006 // coordinates of the current texture, with (0,0) corresponding to 2007 // coordinates of the current texture, with (0,0) corresponding to
2007 // the center of the top-left pixel 2008 // the center of the top-left pixel
2008 boost::shared_ptr<OrthancStone::AnnotationsSceneLayer> stoneAnnotations_; 2009 boost::shared_ptr<OrthancStone::AnnotationsSceneLayer> stoneAnnotations_;
2009 2010
2011 boost::shared_ptr<Orthanc::ImageAccessor> deepLearningMask_;
2012 std::string deepLearningSopInstanceUid_;
2013 unsigned int deepLearningFrameNumber_;
2014
2010 2015
2011 void ScheduleNextPrefetch() 2016 void ScheduleNextPrefetch()
2012 { 2017 {
2013 while (!prefetchQueue_.empty()) 2018 while (!prefetchQueue_.empty())
2014 { 2019 {
2226 annotationsOsiriX->AddLayer(factory.Create(annotation, plane)); 2231 annotationsOsiriX->AddLayer(factory.Create(annotation, plane));
2227 } 2232 }
2228 } 2233 }
2229 } 2234 }
2230 2235
2236 std::unique_ptr<OrthancStone::LookupTableTextureSceneLayer> deepLearningLayer;
2237
2238 if (deepLearningMask_.get() != NULL &&
2239 deepLearningSopInstanceUid_ == instance.GetSopInstanceUid() &&
2240 deepLearningFrameNumber_ == frameIndex)
2241 {
2242 std::vector<uint8_t> lut(4 * 256);
2243 for (unsigned int v = 128; v < 256; v++)
2244 {
2245 lut[4 * v] = 196;
2246 lut[4 * v + 1] = 0;
2247 lut[4 * v + 2] = 0;
2248 lut[4 * v + 3] = 196;
2249 }
2250
2251 deepLearningLayer.reset(new OrthancStone::LookupTableTextureSceneLayer(*deepLearningMask_));
2252 deepLearningLayer->SetLookupTable(lut);
2253 deepLearningLayer->SetPixelSpacing(pixelSpacingX, pixelSpacingY);
2254 deepLearningLayer->SetFlipX(flipX_);
2255 deepLearningLayer->SetFlipY(flipY_);
2256 }
2257
2231 StoneAnnotationsRegistry::GetInstance().Load(*stoneAnnotations_, instance.GetSopInstanceUid(), frameIndex); 2258 StoneAnnotationsRegistry::GetInstance().Load(*stoneAnnotations_, instance.GetSopInstanceUid(), frameIndex);
2232 2259
2233 { 2260 {
2234 std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_->Lock()); 2261 std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport_->Lock());
2235 2262
2251 scene.SetLayer(LAYER_ANNOTATIONS_OSIRIX, annotationsOsiriX.release()); 2278 scene.SetLayer(LAYER_ANNOTATIONS_OSIRIX, annotationsOsiriX.release());
2252 } 2279 }
2253 else 2280 else
2254 { 2281 {
2255 scene.DeleteLayer(LAYER_ANNOTATIONS_OSIRIX); 2282 scene.DeleteLayer(LAYER_ANNOTATIONS_OSIRIX);
2283 }
2284
2285 if (deepLearningLayer.get() != NULL)
2286 {
2287 scene.SetLayer(LAYER_DEEP_LEARNING, deepLearningLayer.release());
2288 }
2289 else
2290 {
2291 scene.DeleteLayer(LAYER_DEEP_LEARNING);
2256 } 2292 }
2257 2293
2258 stoneAnnotations_->Render(scene); // Necessary for "FitContent()" to work 2294 stoneAnnotations_->Render(scene); // Necessary for "FitContent()" to work
2259 2295
2260 if (fitNextContent_) 2296 if (fitNextContent_)
3317 } 3353 }
3318 } 3354 }
3319 } 3355 }
3320 3356
3321 3357
3322 bool GetCurrentFrame(std::string& sopInstanceUid, 3358 bool GetCurrentFrame(std::string& sopInstanceUid /* out */,
3323 unsigned int& frameNumber) const 3359 unsigned int& frameNumber /* out */) const
3324 { 3360 {
3325 if (cursor_.get() != NULL && 3361 if (cursor_.get() != NULL &&
3326 frames_.get() != NULL) 3362 frames_.get() != NULL)
3327 { 3363 {
3328 const size_t cursorIndex = cursor_->GetCurrentIndex(); 3364 const size_t cursorIndex = cursor_->GetCurrentIndex();
3332 return true; 3368 return true;
3333 } 3369 }
3334 else 3370 else
3335 { 3371 {
3336 return false; 3372 return false;
3373 }
3374 }
3375
3376
3377 void SetDeepLearningMask(const std::string& sopInstanceUid,
3378 unsigned int frameNumber,
3379 const Orthanc::ImageAccessor& mask)
3380 {
3381 std::string currentSopInstanceUid;
3382 unsigned int currentFrameNumber;
3383 if (GetCurrentFrame(currentSopInstanceUid, currentFrameNumber) &&
3384 sopInstanceUid == currentSopInstanceUid &&
3385 frameNumber == currentFrameNumber)
3386 {
3387 deepLearningSopInstanceUid_ = sopInstanceUid;
3388 deepLearningFrameNumber_ = frameNumber;
3389 deepLearningMask_.reset(Orthanc::Image::Clone(mask));
3390 Redraw();
3337 } 3391 }
3338 } 3392 }
3339 }; 3393 };
3340 3394
3341 3395
3812 ); 3866 );
3813 3867
3814 if (response.step().done()) 3868 if (response.step().done())
3815 { 3869 {
3816 deepLearningState_ = DeepLearningState_Waiting; 3870 deepLearningState_ = DeepLearningState_Waiting;
3817 LOG(WARNING) << "SUCCESS! Mask: " << response.step().output().width() << "x" 3871
3818 << response.step().output().height() << " for frame " 3872 const unsigned int height = response.step().mask().height();
3819 << response.step().output().sop_instance_uid() << " / " 3873 const unsigned int width = response.step().mask().width();
3820 << response.step().output().frame_number(); 3874
3875 LOG(WARNING) << "SUCCESS! Mask: " << width << "x" << height << " for frame "
3876 << response.step().mask().sop_instance_uid() << " / "
3877 << response.step().mask().frame_number();
3878
3879 Orthanc::Image mask(Orthanc::PixelFormat_Grayscale8, width, height, false);
3880
3881 size_t pos = 0;
3882 for (unsigned int y = 0; y < height; y++)
3883 {
3884 uint8_t* p = reinterpret_cast<uint8_t*>(mask.GetRow(y));
3885 for (unsigned int x = 0; x < width; x++, p++, pos++)
3886 {
3887 *p = response.step().mask().values(pos) ? 255 : 0;
3888 }
3889 }
3890
3891 for (Viewports::iterator it = allViewports_.begin(); it != allViewports_.end(); ++it)
3892 {
3893 assert(it->second != NULL);
3894 it->second->SetDeepLearningMask(response.step().mask().sop_instance_uid(),
3895 response.step().mask().frame_number(), mask);
3896 }
3821 } 3897 }
3822 else 3898 else
3823 { 3899 {
3824 DeepLearningNextStep(); 3900 DeepLearningNextStep();
3825 } 3901 }