Extracting points from images, plots using IDL
written by joehall@pobox.com
|
(aka, "I've got this dang figure and can't get access to the
original data (or at least not fast enough)... how do I extract the
data points from the plot / image?") |
So you would like to extract points from a figure and you have access
to IDL? Well, you're lucky that I've written the code for it:
http://pobox.com/~joehall/export/extract_points.pro
;+
; NAME:
; extract_points
;
; PURPOSE:
;
; To facilitate the extraction of data points from a JPEG figure.
;
; EXPLANATION:
;
; extract_points is pretty simple. It reads in a JPEG file,
; re-sizes it, and then prompts the user to do a bunch of
; clicking to define the axes and then select points to output.
;
; CALLING SEQUENCE:
;
; extract_points, file, out_arr $
; [, xsize=XSIZE, retain=RETAIN]
;
; INPUTS:
;
; file - a simple string that holds the JPEG filename.
;
; OPTIONAL INPUT:
;
; xsize - the number of x pixels in the display window (tv) used
; for clicking. Practically, his is a limit on the
; resolution of your output... the fewer pixels you have
; the more of a limit on your resolution. The maximum
; resolution is practically the edge of your screen
; (unless you can click of the edge of the screen). The
; default is 640 pixels. The y-size is calculated from
; measuring the aspect ratio of the inputted image so
; there is no need for a 'ysize' input.
;
; retain - this is just used for the window initialization. If
; you are using the program and find chunks taken out
; of your display window when you go back and forth,
; set this to two (retain=2).
;
; OUTPUT:
;
; out_arr - a n x 2 floating point array with n being the number
; of points the user clicked on. The other dimensions
; are x and y values respectively (that is,
; out_arr[*,0] is all x-values...)
;
; OPERATIONAL NOTES:
;
; -There's no provisioning for logarithmic axes yet. I'm sure
; someone could add this...
;
; PROCEDURES CALLED:
;
; read_jpeg, congrid(), window, tv, print, cursor, read, sort(),
; poly(), fltarr().
;
; REVISION HISTORY:
; Written by: Joseph Lorenzo Hall, 18 Feb 2003.
; Copyright (c) Joseph Lorenzo Hall 2003
; Modified to handle 24-bit JPEGs; JLH 18 Feb 2003.
;
;###########################################################################
;
; LICENSE
;
; This program is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License as
; published by the Free Software Foundation; either version 2 of the
; License, or (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
; General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
; 02111-1307 USA
;
; If the Internet and WWW are still functional when you are using
; this, you shold be able to access the GPL here:
; http://www.gnu.org/copyleft/gpl.html
;-
pro extract_points, file, out_arr, xsize=XSIZE, retain=RETAIN
read_jpeg, file, im ;READ IN JPEG
;stop
;RESIZE AND DISPLAY JPEG
if n_elements(xsize) ne 1 then $
x_pix = 640 else x_pix=xsize ;SET WINDOW SIZE
im_sz = size(im) ;GET IMAGE DIMENSIONS
jpg_type = im_sz[0]
if jpg_type eq 2 then begin ;8-BIT, 16-BIT
im_sz = size(im,/dim)
aspect = float(im_sz[1]) / float(im_sz[0]) ;ASPECT RATIO
new_im = congrid(im,x_pix,x_pix*aspect) ;RESIZE IMAGE
endif
if jpg_type eq 3 then begin ;24-BIT
im_sz = size(im,/dim)
aspect = float(im_sz[2]) / float(im_sz[1]) ;ASPECT RATIO
new_im = $
congrid(im,im_sz[0],x_pix,x_pix*aspect) ;RESIZE IMAGE
endif
if (jpg_type ne 2) and (jpg_type ne 3) then message, $
'This program does not know what format your JPEG is in.'
window, retain=retain, xsize=x_pix, $ ;OPEN A SIZED WINDOW
ysize=x_pix*aspect
CASE StrUpCase(!D.Name) OF ;FANNING SUGGESTS THIS
'WIN': Device, Decomposed=1
'MAC': Device, Decomposed=1
'X' : Device, Decomposed=1
ELSE:
ENDCASE
if jpg_type eq 3 then $
tv, new_im, true=1 ;DISPLAY JPEG IN WINDOW
if jpg_type eq 2 then $
tv, new_im ;DISPLAY JPEG IN WINDOW
;PROMPT TO CLICK ON A TICK LABELS ON X-AXIS
print, ' '
print, ' Please click on the FIRST labeled tick mark on the X-AXIS"
cursor, x1_x, x1_y, /normal, /down ;RECORD CLICK
print, ' Please enter the label of this tick mark:"
read, x1_val
print, ' Please click on the LAST labeled tick mark on the X-AXIS"
cursor, x2_x, x2_y, /normal, /down ;RECORD CLICK
print, ' Please enter the label of this tick mark:"
read, x2_val
;THE FOLLOWING ALLOWS A TRANFORMATION FROM NORMAL TO DATA COORDINATES
;AS SO: DATA_COORDS = NORMAL_COORDS * X_SCALE + X_INT
x_pix_diff = x2_x - x1_x
x_val_diff = x2_val - x1_val
x_scale = x_val_diff / x_pix_diff ;SLOPE
x_int = x1_val - x1_x * x_scale ;INTERCEPT
;PROMPT TO CLICK ON A TICK LABEL ON Y-AXIS
print, ' '
print, ' Please click on the FIRST labeled tick mark on the Y-AXIS"
cursor, y1_x, y1_y, /normal, /down ;RECORD CLICK
print, ' Please enter the label of this tick mark:"
read, y1_val
print, ' Please click on the LAST labeled tick mark on the Y-AXIS"
cursor, y2_x, y2_y, /normal, /down ;RECORD CLICK
print, ' Please enter the label of this tick mark:"
read, y2_val
;THE FOLLOWING ALLOWS A TRANFORMATION FROM NORMAL TO DATA COORDINATES
;AS SO: DATA_COORDS = NORMAL_COORDS * Y_SCALE + Y_INT
y_pix_diff = y2_y - y1_y
y_val_diff = y2_val - y1_val
y_scale = y_val_diff / y_pix_diff ;SLOPE
y_int = y1_val - y1_y * y_scale ;INTERCEPT
cfx = [x_int,x_scale] ;SAVE COEFFS. FOR POLY()
cfy = [y_int,y_scale]
repeat begin ;BEGIN DATA CLICKING/ SELECTION
print, ' '
print, ' Begin pixel input. Click on a data point to add it to your array.'
print, ' Click on middle or right button to exit.'
flag = 0 ;SET FLAG FOR ARRAY HANDLING
repeat begin
cursor, x, y, /normal, /down
;SAVE PIXELS WHEN LEFT BUTTON CLICKED
if !mouse.button eq 1 then begin
if flag ne 1 then begin ;NEED TO CREATE ARRAY IF NOT PRESENT
flag = 1
x_arr = x & y_arr = y
endif else begin ;DO THIS IF IT'S ALREADY CREATED
x_arr = [x_arr,x] & y_arr = [y_arr,y]
endelse
endif
endrep until !mouse.button ge 2 ;WHEN THE USER CLICKS ANOTHER BUTTON
npts = n_elements(x_arr) ;NUMBER OF CLICKS
as = sort(x_arr) ;SORT 'EM
x_arr = x_arr(as) & y_arr = y_arr(as)
out_arr = fltarr(npts,2) ;INITIALIZE OUTPUT ARRAY
out_arr[*,0] = poly(x_arr,cfx) ;TRANSFORMED X-VALUES
out_arr[*,1] = poly(y_arr,cfy) ;TRANSFORMED Y-VALUES
print, "Are you satisfied with your extraction (0=Sure am, 1=Nope)?"
read, ans
endrep until (ans eq 0) ;END WHEN USER IS SATISFIED
end
|