Commit 89fa886c by Sushil BHATTACHARJEE

### Merge branch 'cleanup' into 'master'

```speed-up code in some critical places

See merge request !2```
parents 25391245 de7369fd
Pipeline #10498 failed with stages
in 7 minutes and 42 seconds
 ... ... @@ -727,36 +727,26 @@ def edge_thinning(bx, by, thinning=1): # np.spacing(1) is the same as eps in matlab. myEps = np.spacing(1) * 100.0 # compute the edge-map a la Matlab for r in range(m): for c in range(n): if thinning: if r < 0 or r > (m - 1) or (c - 1) < 0: b1 = True else: b1 = (b[r, c - 1] < b[r, c]) if(r < 0) or r > (m - 1) or (c + 1) > (n - 1): b2 = True if not thinning: e = b > cutoff else: b2 = (b[r, c] > b[r, c + 1]) b1 = np.ones_like(b, dtype=bool) b2 = np.ones_like(b, dtype=bool) b3 = np.ones_like(b, dtype=bool) b4 = np.ones_like(b, dtype=bool) if (c < 0) or c > (n - 1) or (r - 1) < 0: b3 = True else: b3 = (b[r, c] > b[r - 1, c]) c1 = b > cutoff if(c < 1) or c > (n - 1) or (r + 1) > (m - 1): b4 = True else: b4 = (b[r, c] > b[r + 1, c]) b1[:, 1:] = (np.roll(b, 1, axis=1) < b)[:, 1:] b2[:, :-1] = (np.roll(b, -1, axis=1) < b)[:, :-1] c2 = (bx >= (by - myEps)) & b1 & b2 c1 = (b[r, c] > cutoff) c2 = ((bx[r, c] >= (by[r, c] - myEps)) & b1 & b2) c3 = ((by[r, c] >= (bx[r, c] - myEps)) & b3 & b4) b3[1:, :] = (np.roll(b, 1, axis=0) < b)[1:, :] b4[:-1, 1:] = (np.roll(b, -1, axis=0) < b)[:-1, 1:] c3 = (by >= (bx - myEps)) & b3 & b4 e[r, c] = c1 & (c2 | c3) else: e[r, c] = (b[r, c] > cutoff) e = c1 & (c2 | c3) return e ... ... @@ -813,33 +803,17 @@ def angle_similarity(refImage, testImage, diffImage): refNorm = np.linalg.norm(refImage, axis=1) testNorm = np.linalg.norm(testImage, axis=1) thetaVec = np.zeros([refImage.shape[0], 1]) diffNorm = np.linalg.norm(diffImage, axis=1) magnitVec = diffNorm / 255.0 # Galbally divides by sqrt(255**2) magnitVec = np.reshape(magnitVec, (refImage.shape[0], 1)) for i in range(refImage.shape[0]): refR = refImage[i, :] testR = testImage[i, :] cosTheta = np.dot(refR, testR) / (refNorm[i] * testNorm[i]) if(cosTheta < -1.0): cosTheta = -1.0 if(cosTheta > 1.0): cosTheta = 1.0 theta = np.arccos(cosTheta) thetaVec[i] = theta # the following (commented out) code should be more efficient than the for- # loop above, but seems to be buggy. # rowDP= np.diag(np.dot(refImage,testImage.T)) # normRefrows= np.linalg.norm(refImage,axis=1) # normTestrows= np.linalg.norm(testImage,axis=1) # cosThetaVec = rowDP/(normRefrows * normTestrows) # cosThetaVec = np.nan_to_num(cosThetaVec) #nan occurs when one of the # # norms is 0, ie. vector is all 0s. In that case set cosTheta to 0 # thetaVec = np.arccos(cosThetaVec) # np.einsum('ij,ij->i',a,b) is equivalent to np.diag(np.dot(a,b.T)) cosTheta = np.einsum('ij,ij->i', refImage, testImage) / \ (refNorm * testNorm) cosTheta[cosTheta < -1.0] = -1.0 cosTheta[cosTheta > 1.0] = 1.0 cosTheta = np.nan_to_num(cosTheta) thetaVec = np.arccos(cosTheta).reshape((refImage.shape[0], 1)) tmp2 = thetaVec * 2.0 / np.pi ... ...
 ... ... @@ -399,13 +399,17 @@ def rgbhist(image, maxval, nBins, normType=0): im = image.reshape(3, numPix).copy() im = im.T for i in range(0, numPix): # for i=1:size(I,1)*size(I,2) p = (im[i, :]).astype(float) # p = double(im(i,:)); # p = floor(p/(maxval/nBins))+1; p = (np.floor(p / decimator)).astype(np.uint32) # H(p(1),p(2),p(3)) = H(p(1),p(2),p(3)) + 1; H[p[0], p[1], p[2]] += 1 # end p = np.floor(im.astype(float) / decimator).astype(np.uint32) # in future versions of numpy (1.13 and above) you can replace this with: # unique_p, count = np.unique(p, return_counts=True, axis=0) # the following lines were taken from: https://stackoverflow.com/a/16973510 p2 = np.ascontiguousarray(p).view( np.dtype((np.void, p.dtype.itemsize * p.shape[1]))) unique_p, count = np.unique(p2, return_counts=True) unique_p = unique_p.view(p.dtype).reshape(-1, p.shape[1]) # till here H[unique_p[:, 0], unique_p[:, 1], unique_p[:, 2]] = count H = H.ravel() # H = H(:); # Un-Normalized histogram ... ...
 ... ... @@ -130,10 +130,7 @@ def specular_free_image(src, srcPixelStatus=None): ":: srcPixelStatus should be None, or should match the " \ "pixel-layout of src." for y in range(src.shape[1]): for x in range(src.shape[2]): if np.all(src[:, y, x] < camDark): srcPixelStatus[y, x] = G_CAMERA_DARK srcPixelStatus[np.logical_and.reduce(src < camDark, 0)] = G_CAMERA_DARK srcMaxChroma, srcMax, srcTotal = max_chroma(src) ... ... @@ -181,10 +178,9 @@ def iteration(src, srcPixelStatus, sfi, epsilon, verboseFlag=True): count, srcPixelStatus = init_labels(src, sfi, epsilon, srcPixelStatus) while(1): maxY, maxX = src.shape[-2:] srcMaxChroma, srcMax, srcTotal = max_chroma(src) srcChroma, srcTotal = rgb_chroma(src, srcTotal) maxY = src.shape[1] maxX = src.shape[2] red_chroma_diff_x = np.diff(srcChroma[0, :, :], axis=1) red_chroma_diff_y = np.diff(srcChroma[0, :, :], axis=0) ... ... @@ -192,12 +188,141 @@ def iteration(src, srcPixelStatus, sfi, epsilon, verboseFlag=True): grn_chroma_diff_x = np.diff(srcChroma[1, :, :], axis=1) grn_chroma_diff_y = np.diff(srcChroma[1, :, :], axis=0) # if verboseFlag: # print('.') # a non-complete attempt to remove the for loop below # # find non G_CAMERA_DARK pixels # non_g_camera_dark = (srcPixelStatus != G_CAMERA_DARK) # non_g_camera_dark[-1, :] = False # non_g_camera_dark[:, -1] = False # g_specularx = (non_g_camera_dark) & \ # (srcPixelStatus == G_SPECULARX) # g_speculary = (non_g_camera_dark) & \ # (srcPixelStatus == G_SPECULARY) # '''for specular y''' # # if it is a boundary in x # boundary_x = np.zeros_like(g_specularx) # boundary_x[:-1, :-1] = g_specularx[:-1, :-1] & \ # (np.fabs(red_chroma_diff_x[:-1, :]) > thR) & \ # (np.fabs(grn_chroma_diff_x[:-1, :]) > thG) # srcPixelStatus[boundary_x] = G_BOUNDARY # # if it is noise in x # srcMaxChromaDiffX = np.diff(srcMaxChroma, axis=1) # srcMaxChromaAbsDiffX = np.fabs(srcMaxChromaDiffX) # noise_mask_x = g_specularx & (~boundary_x) # noise_mask_x[:-1, :-1] = noise_mask_x[:-1, :-1] & \ # (srcMaxChromaAbsDiffX[:-1, :] < 0.01) # srcPixelStatus[noise_mask_x] = G_NOISE # # if it is a boundary in x # boundary_y = np.zeros_like(g_speculary) # boundary_y[:-1, :-1] = g_speculary[:-1, :-1] & \ # (np.fabs(red_chroma_diff_y[:, :-1]) > thR) & \ # (np.fabs(grn_chroma_diff_y[:, :-1]) > thG) # srcPixelStatus[boundary_y] = G_BOUNDARY # # if it is noise in x # srcMaxChromaDiffY = np.diff(srcMaxChroma, axis=0) # srcMaxChromaAbsDiffY = np.fabs(srcMaxChromaDiffY) # noise_mask_y = g_speculary & (~boundary_y) # noise_mask_y[:-1, :-1] = noise_mask_y[:-1, :-1] & \ # (srcMaxChromaAbsDiffY[:, :-1] < 0.01) # srcPixelStatus[noise_mask_y] = G_NOISE # # if it is not noise or boundary # boundary_x = np.zeros_like(g_specularx) # boundary_x[:-1, :-1] = g_specularx[:-1, :-1] & \ # (np.fabs(red_chroma_diff_x[:-1, :]) > thR) & \ # (np.fabs(grn_chroma_diff_x[:-1, :]) > thG) # srcMaxChromaDiffX = np.diff(srcMaxChroma, axis=1) # srcMaxChromaAbsDiffX = np.fabs(srcMaxChromaDiffX) # noise_mask_x = g_specularx & (~boundary_x) # noise_mask_x[:-1, :-1] = noise_mask_x[:-1, :-1] & \ # (srcMaxChromaAbsDiffX[:-1, :] < 0.01) # non_noise_mask_x = g_specularx & (~boundary_x) & (~noise_mask_x) # srcPixelStatus[non_noise_mask_x] = G_DIFFUSE # non_noise_mask_next_x = np.roll(non_noise_mask_x, 1, axis=1) # srcPixelStatus[non_noise_mask_next_x] = G_DIFFUSE # boundary_y = np.zeros_like(g_speculary) # boundary_y[:-1, :-1] = g_speculary[:-1, :-1] & \ # (np.fabs(red_chroma_diff_y[:, :-1]) > thR) & \ # (np.fabs(grn_chroma_diff_y[:, :-1]) > thG) # srcMaxChromaDiffY = np.diff(srcMaxChroma, axis=0) # srcMaxChromaAbsDiffY = np.fabs(srcMaxChromaDiffY) # noise_mask_y = g_speculary & (~boundary_y) # noise_mask_y[:-1, :-1] = noise_mask_y[:-1, :-1] & \ # (srcMaxChromaAbsDiffY[:, :-1] < 0.01) # non_noise_mask_y = g_speculary & (~boundary_y) & (~noise_mask_y) # srcPixelStatus[non_noise_mask_y] = G_DIFFUSE # non_noise_mask_next_y = np.roll(non_noise_mask_y, 1, axis=0) # srcPixelStatus[non_noise_mask_next_y] = G_DIFFUSE # # if it is not boundary or noise # pos_chroma_maskx = (srcMaxChromaDiffX[:-1, :] > 0) # reduce_mask_pos_x = non_noise_mask_x.copy() # reduce_mask_pos_x[:-1, :-1] = reduce_mask_pos_x[:-1, :-1] & \ # pos_chroma_maskx # reduce_mask_pos_next_x = np.roll(reduce_mask_pos_x, 1, axis=1) # iro = np.moveaxis(np.moveaxis(src, 0, -1)[reduce_mask_pos_x], -1, 0) # refMaxChroma = srcMaxChroma[reduce_mask_pos_next_x] # iroTotal = srcTotal[reduce_mask_pos_x] # iroMax = srcMax[reduce_mask_pos_x] # iroMaxChroma = srcMaxChroma[reduce_mask_pos_x] # pStat, iroRes = specular_to_diffuse_vectorized( # iro, iroMax, iroMaxChroma, iroTotal, refMaxChroma) # iro[:, pStat != G_NOISE] = iroRes[:, pStat != G_NOISE] # pos_chroma_maskx = ~pos_chroma_maskx # reduce_mask_pos_x = non_noise_mask_x.copy() # reduce_mask_pos_x[:-1, :-1] = reduce_mask_pos_x[:-1, :-1] & \ # pos_chroma_maskx # reduce_mask_pos_next_x = np.roll(reduce_mask_pos_x, 1, axis=1) # iro = np.moveaxis(np.moveaxis(src, 0, -1)[reduce_mask_pos_next_x], # -1, 0) # refMaxChroma = srcMaxChroma[reduce_mask_pos_x] # iroTotal = srcTotal[reduce_mask_pos_next_x] # iroMax = srcMax[reduce_mask_pos_next_x] # iroMaxChroma = srcMaxChroma[reduce_mask_pos_next_x] # pStat, iroRes = specular_to_diffuse_vectorized( # iro, iroMax, iroMaxChroma, iroTotal, refMaxChroma) # iro[:, pStat != G_NOISE] = iroRes[:, pStat != G_NOISE] # # if it is not boundary or noise # pos_chroma_masky = (srcMaxChromaDiffY[:, :-1] > 0) # reduce_mask_pos_y = non_noise_mask_y.copy() # reduce_mask_pos_y[:-1, :-1] = reduce_mask_pos_y[:-1, :-1] & \ # pos_chroma_masky # reduce_mask_pos_next_y = np.roll(reduce_mask_pos_y, 1, axis=1) # iro = np.moveaxis(np.moveaxis(src, 0, -1)[reduce_mask_pos_y], -1, 0) # refMaxChroma = srcMaxChroma[reduce_mask_pos_next_y] # iroTotal = srcTotal[reduce_mask_pos_y] # iroMax = srcMax[reduce_mask_pos_y] # iroMaxChroma = srcMaxChroma[reduce_mask_pos_y] # pStat, iroRes = specular_to_diffuse_vectorized( # iro, iroMax, iroMaxChroma, iroTotal, refMaxChroma) # iro[:, pStat != G_NOISE] = iroRes[:, pStat != G_NOISE] # pos_chroma_masky = ~pos_chroma_masky # reduce_mask_pos_y = non_noise_mask_y.copy() # reduce_mask_pos_y[:-1, :-1] = reduce_mask_pos_y[:-1, :-1] & \ # pos_chroma_masky # reduce_mask_pos_next_y = np.roll(reduce_mask_pos_y, 1, axis=1) # iro = np.moveaxis(np.moveaxis(src, 0, -1)[reduce_mask_pos_next_y], # -1, 0) # refMaxChroma = srcMaxChroma[reduce_mask_pos_y] # iroTotal = srcTotal[reduce_mask_pos_next_y] # iroMax = srcMax[reduce_mask_pos_next_y] # iroMaxChroma = srcMaxChroma[reduce_mask_pos_next_y] # pStat, iroRes = specular_to_diffuse_vectorized( # iro, iroMax, iroMaxChroma, iroTotal, refMaxChroma) # iro[:, pStat != G_NOISE] = iroRes[:, pStat != G_NOISE] for y in range(maxY - 1): for x in range(maxX - 1): current_pixel = srcPixelStatus[y, x] if(current_pixel != G_CAMERA_DARK): if(current_pixel == G_CAMERA_DARK): continue drx = red_chroma_diff_x[y, x] dgx = grn_chroma_diff_x[y, x] ... ... @@ -206,18 +331,18 @@ def iteration(src, srcPixelStatus, sfi, epsilon, verboseFlag=True): if(current_pixel == G_SPECULARX): # if it is a boundary in the x direction if((abs(drx) > thR) and (abs(dgx) > thG)): if (abs(drx) > thR) and (abs(dgx) > thG): # pixel right srcPixelStatus[y, x] = G_BOUNDARY continue # if it is a noise elif (abs(srcMaxChroma[y, x] - srcMaxChroma[y, x + 1]) < 0.01): if abs(srcMaxChroma[y, x] - srcMaxChroma[y, x + 1]) < 0.01: srcPixelStatus[y, x] = G_NOISE continue else: # reduce the specularity at x direction if (srcMaxChroma[y, x] < srcMaxChroma[y, x + 1]): # reduce the specularity at x direction if srcMaxChroma[y, x] < srcMaxChroma[y, x + 1]: iro = src[:, y, x] pStat = current_pixel # pStat = current_pixel refMaxChroma = srcMaxChroma[y, x + 1] iroTotal = srcTotal[y, x] iroMax = srcMax[y, x] ... ... @@ -228,14 +353,14 @@ def iteration(src, srcPixelStatus, sfi, epsilon, verboseFlag=True): # update pixelStatus only if # zSpecular2Diffuse() returned pStat as # G_NOISE. if pStat == G_NOISE: srcPixelStatus[y, x] = pStat else: if pStat != G_NOISE: src[:, y, x] = iroRes # else: # srcPixelStatus[y, x] = pStat else: iro = src[:, y, x + 1] pStat = srcPixelStatus[y, x + 1] # pStat = srcPixelStatus[y, x + 1] refMaxChroma = srcMaxChroma[y, x] iroTotal = srcTotal[y, x + 1] iroMax = srcMax[y, x + 1] ... ... @@ -246,26 +371,26 @@ def iteration(src, srcPixelStatus, sfi, epsilon, verboseFlag=True): # update pixelStatus only if # zSpecular2Diffuse() returned pStat as # G_NOISE. if pStat == G_NOISE: srcPixelStatus[y, x + 1] = pStat else: if pStat != G_NOISE: src[:, y, x + 1] = iroRes # else: # srcPixelStatus[y, x + 1] = pStat srcPixelStatus[y, x] = G_DIFFUSE srcPixelStatus[y, x + 1] = G_DIFFUSE if(current_pixel == G_SPECULARY): # if it is a boundary in the y direction if((abs(dry) > thR) and (abs(dgy) > thG)): if (abs(dry) > thR) and (abs(dgy) > thG): # pixel right srcPixelStatus[y, x] = G_BOUNDARY continue # if it is a noise elif (abs(srcMaxChroma[y, x] - srcMaxChroma[y + 1, x]) < 0.01): if abs(srcMaxChroma[y, x] - srcMaxChroma[y + 1, x]) < 0.01: srcPixelStatus[y, x] = G_NOISE continue else: # reduce the specularity in y direction if(srcMaxChroma[y, x] < srcMaxChroma[y + 1, x]): # reduce the specularity in y direction if srcMaxChroma[y, x] < srcMaxChroma[y + 1, x]: iro = src[:, y, x] pStat = current_pixel refMaxChroma = srcMaxChroma[y + 1, x] ... ... @@ -338,7 +463,6 @@ def init_labels(src, sfi, epsilon, srcPixelStatus): old_settings = np.seterr(divide='ignore', invalid='ignore') # to have initial labels count = 0 zTotalSrc = np.sum(src, axis=0) diff_x_src = np.diff(zTotalSrc, axis=1) diff_y_src = np.diff(zTotalSrc, axis=0) ... ... @@ -347,35 +471,29 @@ def init_labels(src, sfi, epsilon, srcPixelStatus): diff_x_sfi = np.diff(zTotalSfi, axis=1) diff_y_sfi = np.diff(zTotalSfi, axis=0) dlog_src_x = np.log(abs(diff_x_src)) dlog_src_y = np.log(abs(diff_y_src)) dlog_sfi_x = np.log(abs(diff_x_sfi)) dlog_sfi_y = np.log(abs(diff_y_sfi)) dlogx = abs(dlog_src_x - dlog_sfi_x) dlogy = abs(dlog_src_y - dlog_sfi_y) maxY = src.shape[1] maxX = src.shape[2] for y in range(1, maxY - 1): for x in range(1, maxX - 1): pStat = srcPixelStatus[y, x] if pStat not in (G_BOUNDARY, G_NOISE, G_CAMERA_DARK, G_DIFFUSE): # Robby Tan's original C++ code doesn't check for # pStat!=G_DIFFUSE, but this speeds up the processing a lot, # and doesn't seem to affect the results. if dlogx[y, x] > epsilon: pStat = G_SPECULARX count += 1 elif dlogy[y, x] > epsilon: pStat = G_SPECULARY count += 1 else: pStat = G_DIFFUSE srcPixelStatus[y, x] = pStat dlog_src_x = np.log(np.fabs(diff_x_src)) dlog_src_y = np.log(np.fabs(diff_y_src)) dlog_sfi_x = np.log(np.fabs(diff_x_sfi)) dlog_sfi_y = np.log(np.fabs(diff_y_sfi)) dlogx = np.fabs(dlog_src_x - dlog_sfi_x) dlogy = np.fabs(dlog_src_y - dlog_sfi_y) # maxY = src.shape[1] # maxX = src.shape[2] valid_values = (G_BOUNDARY, G_NOISE, G_CAMERA_DARK, G_DIFFUSE) notvalid_mask = np.in1d( srcPixelStatus[1:-1, 1:-1], valid_values, invert=True).reshape(srcPixelStatus.shape[0] - 2, -1) dlogx_mask = (notvalid_mask) & (dlogx[1:-1, 1:] > epsilon) dlogy_mask = (notvalid_mask) & (dlogy[1:, 1:-1] > epsilon) & \ (~(dlogx_mask)) diffuse_mask = (notvalid_mask) & (~dlogx_mask) & (~dlogy_mask) count = notvalid_mask.sum() srcPixelStatus[1:-1, 1:-1][dlogx_mask] = G_SPECULARX srcPixelStatus[1:-1, 1:-1][dlogy_mask] = G_SPECULARY srcPixelStatus[1:-1, 1:-1][diffuse_mask] = G_DIFFUSE np.seterr(**old_settings) return count, srcPixelStatus # count is the number of specular pixels ... ... @@ -417,16 +535,46 @@ def specular_to_diffuse(iro, iroMax, iroMaxChroma, iroTotal, refMaxChroma): return pixelStatus, iro ''' reset all pixelStatus labels, except for DARK pixels src is numpy-array of shape (3,maxY, maxX) pixelLabels is a numpy-array of shape (maxY, maxX) Called in zIteration(). ''' # def specular_to_diffuse_vectorized(iro, iroMax, iroMaxChroma, iroTotal, # refMaxChroma): # """Converts a color-pixel from speckled to diffuse, by subtracting a # certain amount from its intensity value in each color channel. # # Args: # iro: 3-element column vector containing the rgb-color values of the # pixel to be processed. # iroMax: max value among the elements of iro # iroMaxChroma: max-chroma for this pixel # iroTotal: sum of the 3 elements of iro. # refMaxChroma: chroma-value of a neighboring pixel for comparison # # Returns: # pixelStatus: a value (marker) indicating whether the pixel is # considered as noise or diffuse, after processing. # iro: updated pixel-color-values. # """ # c = iroMaxChroma # # arbitrary initialization # pixelStatus = np.empty((*iro.shape[1:]), dtype=iro.dtype) # numr = (iroMax * (3.0 * c - 1.0)) # denm = (c * (3.0 * refMaxChroma - 1.0)) # # non_zero = np.fabs(denm) > 0.000000001 # dI = numr[non_zero] / denm[non_zero] # sI = (iroTotal[non_zero] - dI) / 3.0 # nrgb = iro[:, non_zero] - sI # negnrgb = np.logical_or.reduce(nrgb < 0, axis=0) # # pixelStatus[non_zero][negnrgb] = G_NOISE # iro[:, non_zero][:, ~negnrgb] = nrgb[:, ~negnrgb] # pixelStatus[~non_zero] = G_NOISE # # return pixelStatus, iro def reset_labels(pixelLabels): """Resets all pixel-markers (except those indicating "dark" pixels, to 0. Called in zIteration(). Args: pixelLabels: numpy array of shape (maxX, maxY) containing pixel- ... ... @@ -533,8 +681,7 @@ def rgb_chroma(rgbImg, rgbTotal=None): old_settings = np.seterr(divide='ignore', invalid='ignore') rgbChroma = np.divide(rgbImg.astype(float), rgbTotal.astype(float)) np.seterr(**old_settings) for p in range(rgbChroma.shape[0]): rgbChroma[p, (rgbTotal == 0)] = 0 rgbChroma[:, rgbTotal == 0] = 0 return rgbChroma, rgbTotal ... ...
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment