diff --git a/histomics_label/web_client/views/body/ActiveLearningView.js b/histomics_label/web_client/views/body/ActiveLearningView.js index 0c38750..f11c67f 100644 --- a/histomics_label/web_client/views/body/ActiveLearningView.js +++ b/histomics_label/web_client/views/body/ActiveLearningView.js @@ -522,6 +522,9 @@ const ActiveLearningView = View.extend({ return; } const annotation = this.annotationsByImageId[imageId].predictions.get('annotation'); + if (annotation && annotation.attributes && annotation.attributes.overlappingSuperpixels) { + store.overlappingSuperpixels = annotation.attributes.overlappingSuperpixels; + } const labels = this.annotationsByImageId[imageId].labels.get('annotation'); const labelValues = labels.elements[0].values; const userData = annotation.elements[0].user; @@ -566,6 +569,7 @@ const ActiveLearningView = View.extend({ const version = imageAndJob[0].split(':')[1]; const jobInfo = ((dockerImages[image] || {})[version] || {})[imageAndJob[1]]; if (!jobInfo) { + console.error('Unable to find specified superpixel classification image.'); throw new Error('Unable to find specified superpixel classification image.'); } return this.getJobCertaintyAndFeatureChoices(jobInfo.xmlspec); diff --git a/histomics_label/web_client/views/vue/components/ActiveLearning/ActiveLearningFilmStrip.vue b/histomics_label/web_client/views/vue/components/ActiveLearning/ActiveLearningFilmStrip.vue index f2951fd..ffa436c 100644 --- a/histomics_label/web_client/views/vue/components/ActiveLearning/ActiveLearningFilmStrip.vue +++ b/histomics_label/web_client/views/vue/components/ActiveLearning/ActiveLearningFilmStrip.vue @@ -100,7 +100,7 @@ export default { store.pageSize = Math.floor(width / (cardWidth + padding)); // update page store.page = Math.floor(currentIndex / store.pageSize); - store.maxPage = Math.ceil((store.sortedSuperpixelIndices.length) / store.pageSize) - 1; + store.maxPage = Math.max(Math.ceil((store.sortedSuperpixelIndices.length) / store.pageSize) - 1, 0); // update selected index store.selectedIndex = currentIndex - (store.pageSize * store.page); updateSelectedPage(); diff --git a/histomics_label/web_client/views/vue/components/ActiveLearning/ActiveLearningFilmStripCard.vue b/histomics_label/web_client/views/vue/components/ActiveLearning/ActiveLearningFilmStripCard.vue index e000f20..d5b9777 100644 --- a/histomics_label/web_client/views/vue/components/ActiveLearning/ActiveLearningFilmStripCard.vue +++ b/histomics_label/web_client/views/vue/components/ActiveLearning/ActiveLearningFilmStripCard.vue @@ -77,6 +77,7 @@ export default Vue.extend({ const thumbnailWidth = Math.floor(125 * regionWidth / scaleFactor); const thumbnailHeight = Math.floor(125 * regionHeight / scaleFactor); const params = `?left=${bbox[0] / scale}&top=${bbox[1] / scale}&right=${bbox[2] / scale}&bottom=${bbox[3] / scale}&width=${thumbnailWidth}&height=${thumbnailHeight}&encoding=PNG`; + const mask = store.overlappingSuperpixels ? [0,0,0,0] : [255,255,255,255]; const functionJson = JSON.stringify({ function: { name: 'large_image.tilesource.stylefuncs.maskPixelValues', @@ -84,7 +85,7 @@ export default Vue.extend({ parameters: { values: pixelVals, positive: [0, 0, 0, 0], - negative: [255, 255, 255, 255] + negative: mask, } }, bands: [] diff --git a/histomics_label/web_client/views/vue/components/ActiveLearningReview/ActiveLearningReviewCard.vue b/histomics_label/web_client/views/vue/components/ActiveLearningReview/ActiveLearningReviewCard.vue index 0633e93..56a3b0d 100644 --- a/histomics_label/web_client/views/vue/components/ActiveLearningReview/ActiveLearningReviewCard.vue +++ b/histomics_label/web_client/views/vue/components/ActiveLearningReview/ActiveLearningReviewCard.vue @@ -38,6 +38,7 @@ export default Vue.extend({ const scale = this.superpixel.scale; const thumbnailSize = this.previewSize * 100; const params = `?left=${bbox[0] / scale}&top=${bbox[1] / scale}&right=${bbox[2] / scale}&bottom=${bbox[3] / scale}&width=${thumbnailSize}&height=${thumbnailSize}&encoding=PNG`; + const mask = store.overlappingSuperpixels ? [0,0,0,0] : [255,255,255,255]; const functionJson = JSON.stringify({ function: { name: 'large_image.tilesource.stylefuncs.maskPixelValues', @@ -45,7 +46,7 @@ export default Vue.extend({ parameters: { values: pixelVals, positive: [0, 0, 0, 0], - negative: [255, 255, 255, 255] + negative: mask, } }, bands: [] diff --git a/histomics_label/web_client/views/vue/components/ActiveLearningSlideViewer.vue b/histomics_label/web_client/views/vue/components/ActiveLearningSlideViewer.vue index 6fb70eb..631d721 100644 --- a/histomics_label/web_client/views/vue/components/ActiveLearningSlideViewer.vue +++ b/histomics_label/web_client/views/vue/components/ActiveLearningSlideViewer.vue @@ -444,6 +444,14 @@ export default Vue.extend({ if (newLabel === previousLabel) { return; } + + const bboxes = overlayElement.get('user').bbox + const isEmtpyBackground = index == 0 && bboxes.length >= 4 && bboxes.slice(0, 4).every((val, idx) => val === [0, 0, 1, 1][idx]); + // Don't label the empty background superpixel + if (isEmtpyBackground) { + return; + } + const offset = boundaries ? 1 : 0; data[index] = data[index + offset] = newLabel; store.labelsOverlayLayer.indexModified(index, index + offset).draw(); diff --git a/histomics_label/web_client/views/vue/components/store.js b/histomics_label/web_client/views/vue/components/store.js index e9f9614..18c822c 100644 --- a/histomics_label/web_client/views/vue/components/store.js +++ b/histomics_label/web_client/views/vue/components/store.js @@ -23,6 +23,7 @@ const store = Vue.observable({ zoom: 1, center: { x: 1, y: 1 }, sortedSuperpixelIndices: [], + overlappingSuperpixels: false, reviewSuperpixel: null, currentUser: null, epoch: -1, @@ -87,7 +88,7 @@ const updateSelectedPage = () => { const endIndex = Math.min(startIndex + store.pageSize, store.sortedSuperpixelIndices.length); store.superpixelsToDisplay = store.sortedSuperpixelIndices.slice(startIndex, endIndex); store.currentImageId = store.superpixelsToDisplay[store.selectedIndex].imageId; - store.maxPage = Math.ceil(store.sortedSuperpixelIndices.length / store.pageSize) - 1; + store.maxPage = Math.max(Math.ceil(store.sortedSuperpixelIndices.length / store.pageSize) - 1, 0); }; /**