Mercurial > hg > orthanc-stone
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 } |