Vital signs extraction from scanned charts works when every reading is stored as a complete record: the measurement name, the number, its unit, the date and time it was taken, and the page and grid cell it came from. A number without its unit and time cannot be checked, compared or trusted, so capture all of them together.
Which vital signs fields should you extract?
The vital signs fields to extract are the measurements a chart records at each check, plus the attributes that make each number usable. The measurements are usually blood pressure, heart rate, respiratory rate, temperature, oxygen saturation, height and weight. The attributes are the unit, the time taken, and the source location on the page.
The federal list of core health data gives the standard set. The ONC USCDI Vital Signs data class lists systolic and diastolic blood pressure, heart rate, respiratory rate, body temperature, body height, body weight, pulse oximetry and inhaled oxygen concentration, along with three pediatric percentiles. For each it names LOINC for the measurement type and UCUM for the unit. Vital sign dates and timestamps appear on the same page only as a Level 0 candidate, which means the time is not yet part of the published standard even though no reading makes sense without it.
For extraction, treat every reading as one row with these fields:
| Field | What it holds | Example value (fictional) |
|---|---|---|
| Measurement | Which vital sign | Heart rate |
| Value | The number as read | 72 |
| Unit | The unit printed or implied by the row label | /min |
| Date and time | When the reading was taken | 2025-02-03 08:00 |
| Position or method | Any qualifier printed, such as "sitting" or "oral" | sitting |
| Source | Document, page, row and column | Nursing flowsheet, page 4, row "HR", column 0800 |
| Reviewer note | Why a person checked or changed it | blank |
Blood pressure deserves special handling. It is written as one string, such as 128/82, but it holds two measurements. Store the systolic and diastolic values as separate rows that share a time and source, so a misread on one half can be flagged without discarding the other.
Keep qualifiers that the chart prints, like "standing", "left arm" or "on 2 L oxygen". Do not add ones it does not print. An extracted record describes the page, not the patient.
Reading vital signs flowsheets and grids
A vital signs flowsheet is a grid. Measurement names run down the left side, times or dates run across the top, and each cell holds one reading. Extracting it correctly means keeping every value tied to both its row label and its column header, because the number alone says nothing about what was measured or when.
Grids fail in predictable ways when they are scanned. Thin ruling lines fade, so OCR merges two columns and reads "98.6 99.1" as one value. A reading written across a cell border lands in the wrong column. A blank cell gets skipped, and every value after it shifts one time slot to the left. Each of these produces numbers that look normal and are attached to the wrong time.
A few habits prevent most column errors:
- Read the header row first. Extract every column time before any values, and count them. Every data row should then have the same number of cells, blank or not.
- Keep blanks as blanks. An empty cell is a real result: nothing was recorded at that time. Store it as empty rather than closing the gap.
- Anchor rows by label, not position. Flowsheets from different units put rows in different orders. Match "Temp", "T" and "Temperature" to one measurement name.
- Record the cell, not just the page. A source of "page 4, row RR, column 1200" lets a reviewer find the exact box in seconds.
- Watch multi-page grids. When a flowsheet continues onto the next page, the time header may print only once. Carry it forward and note that you did.
Handwritten flowsheets are harder than printed ones, and OCR on handwriting is less reliable. The question of how well software reads handwritten notes is covered in the guide to whether OCR can read handwritten clinical notes. For vital signs, the practical answer is to send handwritten grid cells to a person more often than printed ones.
Units and times for each vital sign reading
Each vital sign reading needs a unit and a time to mean anything. Temperature may be in Fahrenheit or Celsius, weight in pounds or kilograms, height in inches or centimeters. Times may print in 24-hour or 12-hour format, or only as a shift. Extraction should record the unit and time the chart shows and convert only into a separate field.
Standards make the unit choice explicit. The HL7 FHIR R4 vital signs profile pairs each measurement with a LOINC code and the UCUM units allowed for it: body temperature (8310-5) in Cel or [degF], body weight (29463-7) in g, kg or [lb_av], body height (8302-2) in cm or [in_i], heart rate (8867-4) and respiratory rate (9279-1) per minute, oxygen saturation (2708-6) in percent, and systolic (8480-6) and diastolic (8462-4) blood pressure in mm[Hg]. The profile also requires a time indicating when each measurement was taken.
Charts often omit the unit and rely on the row label or the facility's habit. When the unit is not printed, do not guess silently. Record the unit as "not printed", and if your project infers one, store the inference and the reason in a separate field. An inferred unit, and the reason for it, belongs in a reviewer note, not in the value field, so anyone can filter inferred units out later.
Conversion is arithmetic, and it should never replace the original. Keep the charted value and unit, then add converted fields if the project needs one unit throughout. For example (fictional values): 165 lb is about 74.8 kg, and 99.1 °F is about 37.3 °C. Rounding rules belong in your data dictionary, written down once.
Times have their own edge cases:
- Shift labels like "Day" or "Night" are not times. Store them as written.
- 12-hour times without AM or PM are ambiguous on a 24-hour grid. Flag them.
- Dates that change mid-grid, past midnight, need the date carried to the right columns.
- Readings with no time at all, such as a weight at the top of a visit note, take the visit date and a blank time, marked as such.
Every unit and time you add rather than read should be visible as added.
Scan errors that change vital sign values
Scan errors change vital sign values when OCR misreads a digit, drops a decimal point or joins two cells. Unlike a misspelled word, a wrong number often looks perfectly reasonable, so these errors survive casual review. Knowing which misreads are common tells you where to put checks.
The usual culprits on scanned charts are these:
- Dropped decimal points. A faint dot vanishes, and 98.6 becomes 986, or 36.8 becomes 368.
- Digit swaps. Handwritten 1 and 7, 5 and 6, or 0 and 6 are confused, so 71 becomes 77 or 150 becomes 156.
- Merged cells. Two adjacent readings print close together and come back as one long number.
- Slash loss in blood pressure. 120/80 loses its slash and reads as 12080, or the slash reads as a 1 and the value becomes 120180.
- Unit marks read as digits. A degree sign read as a zero turns 98.6° into 98.60, which is harmless, or 99° into 990, which is not.
A fictional flowsheet excerpt, worked
The patient is fictional: Ruth Vandermeer, encounter 77-4410 (example). The excerpt covers three columns of a scanned nursing flowsheet dated 2025-02-03. Every value is invented for this example.
| Row label | 0800 | 1200 | 1600 |
|---|---|---|---|
| Temp (°F) | 98.4 | 986 | 99.0 |
| HR | 72 | 76 | 74 |
| BP | 124/78 | 12278 | 126/80 |
| RR | 16 | 16 | 61 |
| SpO2 (%) | 97 | 98 | 97 |
The extracted rows for 1200 and 1600 then look like this:
| Measurement | Value as read | Unit | Time | Check result |
|---|---|---|---|---|
| Temperature | 986 | [degF] | 1200 | Outside the team's plausibility limits: likely dropped decimal |
| Blood pressure | 12278 | mm[Hg] | 1200 | Not in systolic/diastolic form: likely lost slash |
| Respiratory rate | 61 | /min | 1600 | Outside the team's plausibility limits: possible digit swap of 16 |
| Heart rate | 74 | /min | 1600 | Passed |
All three flagged values went to a reviewer with the cell highlighted on the scan. The reviewer corrected the temperature and blood pressure from the image and confirmed the respiratory rate cell as charted, which shows why a check should route a value, not rewrite it.
What should happen to an implausible vital sign value?
An implausible vital sign value should go to a person, together with the image of the cell it came from. A range check marks numbers outside limits the project team wrote down in advance, but it never changes or deletes the value. The reviewer reads the page and decides what it says.
Range checks for extraction are data checks, not clinical ones. Their job is to catch readings that are physically impossible or that match a known misread pattern, like a four-digit temperature. The limits come from the team's data dictionary, are wide on purpose, and say nothing about whether a reading is good or bad for a patient. That question is for clinicians and is not part of this work.
Useful checks fall into three groups:
- Format checks: blood pressure must have two parts, oxygen saturation cannot exceed 100 percent, a heart rate is a whole number.
- Plausibility limits: wide bounds per measurement and unit, set by the team, that catch dropped decimals and merged cells.
- Consistency checks: a row label that names one unit while the cell prints another, or the same weight entered twice an hour apart with different numbers.
When a value fails, the record should keep the original value as read, the reason it was flagged, and later the reviewer's decision with their name and the time. That trail lets anyone see which numbers were changed and why. The human review category goes deeper on validation rules and review queues.
This is the workflow Schema Care is designed around: it reads vitals from medical records, scores its confidence in each value, and sends anything below your threshold to a reviewer who sees the field highlighted on the original page, as the human review steps show. Vital signs rarely stand alone in a chart; prescription fields are covered in extracting drug strength, dose and refills from prescriptions, and dating every document in a large chart is covered in finding encounter dates in a long medical record.