X

NV5 Geospatial Blog

Each month, NV5 Geospatial posts new blog content across a variety of categories. Browse our latest posts below to learn about important geospatial information or use the search bar to find a specific topic or author. Stay informed of the latest blog posts, events, and technologies by joining our email list!



Not All Supernovae Are Created Equal: Rethinking the Universe’s Measuring Tools

Not All Supernovae Are Created Equal: Rethinking the Universe’s Measuring Tools

6/3/2025

Rethinking the Reliability of Type 1a Supernovae   How do astronomers measure the universe? It all starts with distance. From gauging the size of a galaxy to calculating how fast the universe is expanding, measuring cosmic distances is essential to understanding everything in the sky. For nearby stars, astronomers use... Read More >

Using LLMs To Research Remote Sensing Software: Helpful, but Incomplete

Using LLMs To Research Remote Sensing Software: Helpful, but Incomplete

5/26/2025

Whether you’re new to remote sensing or a seasoned expert, there is no doubt that large language models (LLMs) like OpenAI’s ChatGPT or Google’s Gemini can be incredibly useful in many aspects of research. From exploring the electromagnetic spectrum to creating object detection models using the latest deep learning... Read More >

From Image to Insight: How GEOINT Automation Is Changing the Speed of Decision-Making

From Image to Insight: How GEOINT Automation Is Changing the Speed of Decision-Making

4/28/2025

When every second counts, the ability to process geospatial data rapidly and accurately isn’t just helpful, it’s critical. Geospatial Intelligence (GEOINT) has always played a pivotal role in defense, security, and disaster response. But in high-tempo operations, traditional workflows are no longer fast enough. Analysts are... Read More >

Thermal Infrared Echoes: Illuminating the Last Gasp of a Dying Star

Thermal Infrared Echoes: Illuminating the Last Gasp of a Dying Star

4/24/2025

This blog was written by Eli Dwek, Emeritus, NASA Goddard Space Flight Center, Greenbelt, MD and Research Fellow, Center for Astrophysics, Harvard & Smithsonian, Cambridge, MA. It is the fifth blog in a series showcasing our IDL® Fellows program which supports passionate retired IDL users who may need support to continue their work... Read More >

A New Era of Hyperspectral Imaging with ENVI® and Wyvern’s Open Data Program

A New Era of Hyperspectral Imaging with ENVI® and Wyvern’s Open Data Program

2/25/2025

This blog was written in collaboration with Adam O’Connor from Wyvern.   As hyperspectral imaging (HSI) continues to grow in importance, access to high-quality satellite data is key to unlocking new insights in environmental monitoring, agriculture, forestry, mining, security, energy infrastructure management, and more.... Read More >

1345678910Last
11798 Rate this article:
3.3

Find the Finder

Anonym

Recently I was tasked with finding a QR code in an image and then computing its location and. I learned that the first step in locating a QR code is discerning the finder points.  In QR codes there are three finder points located at the furthest reaches of three of the corners.  These finder points are made up of white and black pixels and regardless of the rotation of the code, a cross-section of one finder point will look like the following. 

B W B B B W B

B = Black pixel; W = White pixel

With this pattern of points being fixed and the ratio of ring counts, with respect to the center block, being for the outer black ring,  for the inner, white ring, I found that it was possible to use the contour procedure and a little math to pull out these finder points. 

 

Figure 1: Input Image

 

To locate the finder points, I first opened the image and stripped out a single band.  Then I converted the image to a binary image and coded any gaps that were formed by the conversion.

; open envi

e = envi()

 

; open the image

oRaster = e.openRaster(inputfile)

 

; strip out single band

band1 = oRaster.GetData(Bands=0)

 

; convert to binary image

data = band1 gt 128

; close gaps

data =MORPH_Open(data, REPLICATE(1,3,3))

Figure 2: Binary image

Once I had a binary image, I computed the contour lines for the full image. I then added each contour line to the previous contour line. This step results in an image where contours that overlap have a much higher value than those that do not.

; get the contours of the image

contour, data, PATH_INFO=path_info, path_xy=path_xy,$

 /PATH_DATA_COORDS, LEVELS=[0,1]

 

; build overlapping image

overlap_img = bytarr(oRaster.ns, oRaster.nl)

 

; create a container for the ROIs, we will use them again

oROIs = make_array(n_elements(path_info), /OBJ)

 

for i = 0 , n_elements(path_info)-1 do begin

  ; get the end pos

  end_pos = (path_info[i].offset) + (path_info[i].n)-1

 

  ; get the points

  pts = path_xy[*,(path_info[i].offset):end_pos]

 

  ; last point has to be the same as the first

  xs = [[pts[0,*]],[pts[0,0]]]

  ys = [[pts[1,*]],[pts[1,0]]]

 

  ; create the ROI

  oROIs[i] = OBJ_NEW('IDLanROI', xs, ys)

 

  ; compute the mask

  Mask = oROIs[i]->ComputeMask(INITIALIZE=0, DIMENSIONS=[oRaster.ns,$

oRaster.nl],$

       Mask_Rule=2)

 

  ; convert to binary

  Mask = Mask eq 255

 

  ; add the mask to the image

  overlap_img = overlap_img + Mask

 

endfor

Figure 3: Overlapping contour image

Once the overlapping image was created, I searched for regions that satisfy the  and  ring ratio rule. If any contour groups were found, the center of mass of each grouping was recorded.

; get the max number of overlaps in the image

max_overlap = max(overlap_img)

 

; set the desired ratios

desired_ratio1 = 2. + (2./3.)

desired_ratio2 = 1. + (7./9.)

 

; create a container for the finder points

finder_cm = []

 

for i = 0 , n_elements(path_info)-1 do begin

 

  ; compute the mask

  Mask = oROIs[i]->ComputeMask(INITIALIZE=0, DIMENSIONS=[oRaster.ns,$

oRaster.nl],$

       Mask_Rule=2)

 

  ; convert to binary

  Mask = Mask eq 255

 

  ;Mask overlap image

  StudyArea = overlap_img * Mask

 

  ;compute the histogram of the image

  Hist = HISTOGRAM(StudyArea, LOCATIONS=pos, NBINS=nbins, BINSIZE = 1, MIN=1,$

MAX=max_overlap)

 

  ; if there are more or less than 3 values, then discard it

  pos = where(Hist ne 0)

  if n_elements(pos) eq 3 then begin

    ; get the counts for each bin

    vals = float(hist[pos])

 

    ;calculate the ratios

    ;outer black ring / inner

    ratio1 =  vals[0] / vals[2]

    ;white ring / inner

    ratio2 = vals[1] / vals[2]

 

    ; check that the difference is desired ratio

    ratio1_dif_percent = ratio1 / desired_ratio1

    ratio1_dif_percent = abs(ratio1_dif_percent - 1.)

    ratio2_dif_percent = ratio2 / desired_ratio2

    ratio2_dif_percent = abs(ratio2_dif_percent - 1.)

 

    ; if they are within 60%, save as a finder point

    if ratio1_dif_percent lt .3 and ratio2_dif_percent lt .3 then begin

      ; calculate the center of mass

      StudyArea = StudyArea gt 0

      Mass = Total(StudyArea)

      center_x = Total( Total(StudyArea, 2) * Indgen(oRaster.ns) ) / Mass

      center_y = Total( Total(StudyArea, 1) * Indgen(oRaster.nl) ) / Mass

 

      ; record the center

      finder_cm = [[finder_cm],[center_x,center_y]]

 

    endif

  endif

endfor

Last, but not least, I took a moment to plot the results and admire the fruits of my labor.

; display the input image

im = image(oRaster.GetData(interleave='bsq') )

 

; plot the location of the finder points on top of the input image

for i = 0 ,n_elements(finder_cm[0,*])-1 do $

p = SCATTERPLOT(finder_cm[0,i],finder_cm[1,i],$

 OVERPLOT = im, AXIS_STYLE=0, SYM_COLOR='red',$

  SYM_FILL_COLOR='blue', SYM_FILLED=0, SYM_SIZE=2,$

   SYMBOL='o',SYM_THICK=4)

Figure 4: Final results

 

I hope that you got something out of this demo. If not how to locate a finder point, then perhaps how to use contours in a new and exciting way.

Please login or register to post comments.