diff --git a/common/util.js b/common/util.js
index a9fd9d6c0c939b5bb05ef281543f74d56b105a29..6b6df94eb08068247b17e3c9865f055752f3743a 100644
--- a/common/util.js
+++ b/common/util.js
@@ -47,14 +47,13 @@
    *
    * https://stackoverflow.com/a/16348977/6059235
    */
-  exports.intToRgb = int => {
-    if (int >= 65500) {
-      return [255, 255, 255]
-    }
-    const str = String(int * 65535)
+  exports.strToRgb = str => {
+    if (typeof str !== 'string') throw new Error(`strToRgb input must be typeof string !`)
+
     let hash = 0
-    for (let i = 0; i < str.length; i++) {
-      hash = str.charCodeAt(i) + ((hash << 5) - hash);
+    // run at least 2 cycles, or else, len 1 string does not get hashed well
+    for (let i = 0; i < str.length || i < 5; i++) {
+      hash = str.charCodeAt(i % str.length) + ((hash << 5) - hash);
     }
     const returnV = []
     for (let i = 0; i < 3; i++) {
diff --git a/common/util.spec.js b/common/util.spec.js
index 4597a54db648521dd029fb002f22ef56436d3b51..a66f12a39bd1307fbc17573f078937e37d742350 100644
--- a/common/util.spec.js
+++ b/common/util.spec.js
@@ -1,4 +1,4 @@
-import { getIdFromFullId } from './util'
+import { getIdFromFullId, strToRgb } from './util'
 
 describe('common/util.js', () => {
   describe('getIdFromFullId', () => {
@@ -17,4 +17,63 @@ describe('common/util.js', () => {
       expect(getIdFromFullId(fullId)).toBe(`minds/core/parcellationregion/v1.0.0/a844d80f-1d94-41a0-901a-14ae257519db`)
     })
   })
+
+  describe('strToRgb', () => {
+    const str1 = 'hello world'
+    const str2 = 'foo bar'
+    const str3 = 'a'
+    const str4 = 'b'
+    const strArr = [
+      str1,
+      str2,
+      str3,
+      str4,
+    ]
+    it('should return rgb', () => {
+      const outs = strArr.map(strToRgb)
+      for (const out of outs) {
+        expect(
+          out instanceof Array
+        ).toBeTruthy()
+
+        expect(out.length).toEqual(3)
+
+        for (const n of out) {
+          expect(n).toBeGreaterThanOrEqual(0)
+          expect(n).toBeLessThanOrEqual(255)
+        }
+      }
+      
+    })
+
+    it('rgb returned should be disinct', () => {
+
+      const outs = strArr.map(strToRgb)
+      for (let i = 0; i < outs.length; i++) {
+        const compareA = outs[i]
+        for (let j = i + 1; j < outs.length; j++) {
+          const compareB = outs[j]
+          // compare all generated rgb, expect at least 1 of rgb to be of greater than 5 units out
+          expect(
+            compareA.some((n, idx) => Math.abs( n - compareB[idx] ) > 5)
+          ).toBeTruthy()
+        }
+      }
+    })
+
+    it ('should throw if not providing stirng', () => {
+      expect(() => {
+        strToRgb(12)
+      }).toThrow()
+      
+      expect(() => {
+        strToRgb(['hello world'])
+      }).toThrow()
+
+      expect(() => {
+        strToRgb({foo: 'baz'})
+      }).toThrow()
+    })
+  
+  })
 })
diff --git a/docs/releases/v2.4.0.md b/docs/releases/v2.4.0.md
index 6b666247cb284cbf07dc838c64322ccff4c2e187..feec3a1ee6c3b69fc8947a44a436e4183418c16c 100644
--- a/docs/releases/v2.4.0.md
+++ b/docs/releases/v2.4.0.md
@@ -3,6 +3,7 @@
 ## Bugfixes
 
 - fixes UI issue, where chips wraps on smaller screen (#740)
+- regions with the same labelIndex without colour will no longer have the same colour (#750)
 
 ## New features
 
diff --git a/src/atlasComponents/parcellationRegion/region.base.ts b/src/atlasComponents/parcellationRegion/region.base.ts
index 56742360d9194d228b1eda8c529373d48a190fe6..d85da3b272cf525a2bcf54e7feae1a903d3c5935 100644
--- a/src/atlasComponents/parcellationRegion/region.base.ts
+++ b/src/atlasComponents/parcellationRegion/region.base.ts
@@ -7,7 +7,7 @@ import { ARIA_LABELS } from 'common/constants'
 import { flattenRegions, getIdFromFullId, rgbToHsl } from 'common/util'
 import { viewerStateSetConnectivityRegion, viewerStateNavigateToRegion, viewerStateToggleRegionSelect, viewerStateNewViewer, isNewerThan } from "src/services/state/viewerState.store.helper";
 import { viewerStateFetchedTemplatesSelector, viewerStateGetSelectedAtlas, viewerStateSelectedTemplateFullInfoSelector, viewerStateSelectedTemplateSelector } from "src/services/state/viewerState/selectors";
-import { intToRgb, verifyPositionArg, getRegionHemisphere } from 'common/util'
+import { strToRgb, verifyPositionArg, getRegionHemisphere } from 'common/util'
 
 export class RegionBase {
 
@@ -36,7 +36,11 @@ export class RegionBase {
     this.position = val && val.position
     if (!this._region) return
 
-    const rgb = this._region.rgb || (this._region.labelIndex && intToRgb(Number(this._region.labelIndex))) || [255, 200, 200]
+    let rgb = this._region.rgb
+    rgb = rgb || this._region.labelIndex > 65500 ? [255, 255, 255] : null
+    rgb = rgb || strToRgb(`${this._region.ngId || this._region.name}${this._region.labelIndex}`)
+    rgb = rgb || [255, 200, 200]
+    
     this.rgbString = `rgb(${rgb.join(',')})`
     const [_h, _s, l] = rgbToHsl(...rgb)
     this.rgbDarkmode = l < 0.4
diff --git a/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.ts b/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.ts
index 57f4f526ff7651ce098ed165f73e7c835b4a7f2d..dc8112ccf8053657283dde99b665a2eab8506e60 100644
--- a/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.ts
+++ b/src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component.ts
@@ -10,7 +10,7 @@ import { getExportNehuba, getViewer, setNehubaViewer } from "src/util/fn";
 import '!!file-loader?context=third_party&name=main.bundle.js!export-nehuba/dist/min/main.bundle.js'
 import '!!file-loader?context=third_party&name=chunk_worker.bundle.js!export-nehuba/dist/min/chunk_worker.bundle.js'
 import { scanSliceViewRenderFn } from "../util";
-import { intToRgb as intToColour, deserialiseParcRegionId } from 'common/util'
+import { strToRgb, deserialiseParcRegionId } from 'common/util'
 
 const NG_LANDMARK_LAYER_NAME = 'spatial landmark layer'
 const NG_USER_LANDMARK_LAYER_NAME = 'user landmark layer'
@@ -944,7 +944,7 @@ export class NehubaViewerUnit implements OnInit, OnDestroy {
               return [val, {}]
             }),
           ],
-        ).map((val: [number, any]) => ([val[0], this.getRgb(val[0], val[1].rgb)])) as any),
+        ).map((val: [number, any]) => ([val[0], this.getRgb(val[0], { ngId, rgb: val[1].rgb})])) as any),
       ]
     }) as Array<[string, Map<number, {red: number, green: number, blue: number}>]>
 
@@ -987,9 +987,17 @@ export class NehubaViewerUnit implements OnInit, OnDestroy {
     })
   }
 
-  private getRgb(labelIndex: number, rgb?: number[]): {red: number, green: number, blue: number} {
+  private getRgb(labelIndex: number, region: { rgb: number[], ngId: string }): {red: number, green: number, blue: number} {
+    const { rgb, ngId } = region
     if (typeof rgb === 'undefined' || rgb === null) {
-      const arr = intToColour(Number(labelIndex))
+      if (labelIndex > 65500) {
+        return {
+          red: 255,
+          green: 255,
+          blue: 255
+        }
+      }
+      const arr = strToRgb(`${ngId}${labelIndex}`)
       return {
         red : arr[0],
         green: arr[1],