处理礼泉县城关卫生院ocr识别 字段不对应问题 新增LQXSD 方法

This commit is contained in:
lxd 2025-05-14 15:50:46 +08:00
parent 9a29647a42
commit e636f0d273

View File

@ -90,6 +90,9 @@ public class FolderMonitor {
case "CG":
extractedData = processImageWithCG(imageFullPath);
break;
case "LQXSD":
extractedData = processImageWithLQXSD(imageFullPath);
break;
case "normal":
default:
extractedData = processImageNormal(imageFullPath);
@ -750,62 +753,72 @@ public class FolderMonitor {
String pPattern = "P\\s*[:.·]?\\s*([\\dOo./]+[mM][sS])";
String prPattern = "PR\\s*[:.·]?\\s*([\\dOo./]+[mM][sS])";
String qrsPattern = "QRS\\s*[:.·]?\\s*([\\dOo./]+[mM][sS])";
String qtPattern = "QT/QT[cC]?\\s*[:.·]?\\s*([\\dOo./]+[mM][sS])";
String qtPattern = "(?:QT|QI)/QT[cC]?\\s*[:.·]?\\s*([\\dOo./]+[mM][sS])";
String qtcPattern = "[@Q]Tc\\s*间\\s*期\\s*[:]?\\s*(\\d+)\\s*[mM][sS]";
String pqrstPattern = "P/QRS/T\\s*[:.·]?\\s*([\\dOo./]+)";
String rv5sv1Pattern = "([_\\s]*[Rr][Vv5][Ss][\\s/]*[Ss][Vv1Ii])\\s*[:.·]?\\s*([\\dOo./]+)\\s*[mM][vVyY]?";
for (String line : paramLines) {
line = line.replaceAll("\\s+", " ").trim();
if (extractedData.get("HR") == null) {
if (extractedData.get("hr") == null) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile(hrPattern, java.util.regex.Pattern.CASE_INSENSITIVE).matcher(line);
if (m.find()) {
String hrValue = m.group(1).replaceAll("[Oo]", "0").replaceAll("[^\\d.]", "");
extractedData.put("HR", hrValue);
extractedData.put("hr", hrValue);
}
}
if (extractedData.get("P") == null) {
if (extractedData.get("p") == null) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile(pPattern, java.util.regex.Pattern.CASE_INSENSITIVE).matcher(line);
if (m.find()) {
String pValue = m.group(1).replaceAll("[Oo]", "0").replaceAll("[^\\d.]", "");
extractedData.put("P", pValue);
extractedData.put("p", pValue);
}
}
if (extractedData.get("PR") == null) {
if (extractedData.get("pr") == null) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile(prPattern, java.util.regex.Pattern.CASE_INSENSITIVE).matcher(line);
if (m.find()) {
String prValue = m.group(1).replaceAll("[Oo]", "0").replaceAll("[^\\d.]", "");
extractedData.put("PR", prValue);
extractedData.put("pr", prValue);
}
}
if (extractedData.get("QRS") == null) {
if (extractedData.get("qrs") == null) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile(qrsPattern, java.util.regex.Pattern.CASE_INSENSITIVE).matcher(line);
if (m.find()) {
String qrsValue = m.group(1).replaceAll("[Oo]", "0").replaceAll("[^\\d.]", "");
extractedData.put("QRS", qrsValue);
extractedData.put("qrs", qrsValue);
}
}
if (extractedData.get("QT/QTC") == null) {
if (extractedData.get("qt/qtc") == null) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile(qtPattern, java.util.regex.Pattern.CASE_INSENSITIVE).matcher(line);
if (m.find()) {
String qtValue = m.group(1).replaceAll("[Oo]", "0").replaceAll("[^\\d./]", "");
extractedData.put("QT/QTC", qtValue);
extractedData.put("qt/qtc", qtValue);
}
}
if (extractedData.get("P/QRS/T") == null) {
if (extractedData.get("pAxle/qrsAxle/tAxle") == null) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile(pqrstPattern, java.util.regex.Pattern.CASE_INSENSITIVE).matcher(line);
if (m.find()) {
String pqrstValue = m.group(1).replaceAll("[Oo]", "0").replaceAll("[^\\d/degDEG.]", "");
extractedData.put("P/QRS/T", pqrstValue);
extractedData.put("pAxle/qrsAxle/tAxle", pqrstValue);
}
}
if (extractedData.get("RV5/SV1") == null) {
if (extractedData.get("rv5/sv1") == null) {
if (line.toLowerCase().contains("sv1")) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile("([\\dOo.]+)/([\\dOo.]+)\\s*[mM][vVyY]").matcher(line);
if (m.find()) {
String rv5 = m.group(1).replaceAll("[Oo]", "0");
String sv1 = m.group(2).replaceAll("[Oo]", "0");
String rv5sv1Value = rv5 + "/" + sv1;
extractedData.put("RV5/SV1", rv5sv1Value);
extractedData.put("rv5/sv1", rv5sv1Value);
// 计算rv5Sv1的值rv5和sv1的和
try {
double rv5Value = Double.parseDouble(rv5);
double sv1Value = Double.parseDouble(sv1);
double sum = rv5Value + sv1Value;
extractedData.put("rv5Sv1", String.format("%.3f", sum));
} catch (NumberFormatException e) {
logger.error("计算rv5Sv1时发生数字格式错误: rv5={}, sv1={}", rv5, sv1, e);
}
}
}
}
@ -837,6 +850,254 @@ public class FolderMonitor {
return extractedData;
}
// 新增礼泉县夹德中心卫生院模板识别方法
private Map<String, String> processImageWithLQXSD(String imageFullPath) {
Map<String, String> extractedData = new HashMap<>();
try {
BufferedImage image = ImageIO.read(new File(imageFullPath));
int width = image.getWidth();
int height = image.getHeight();
// 1. 顶部患者信息区约前12%
int infoHeight = (int) (height * 0.12);
BufferedImage infoArea = image.getSubimage(0, 0, width, infoHeight);
String infoOcr = tesseract.doOCR(infoArea);
String[] infoLines = infoOcr.split("\\r?\\n");
String namePattern = "\\s*名\\s*[:]?\\s*([\\u4e00-\\u9fa5]+)(?=\\s*[门]?诊\\s*号|\\s*性\\s*别|$)";
String genderPattern = "\\s*别\\s*[:]?\\s*([男女])";
String agePattern = "\\s*龄\\s*[:]?\\s*(\\d+)\\s*[岁%]";
String idPattern = "\\s*号\\s*[:;]?\\s*([A-Za-z0-9]+)";
for (String line : infoLines) {
line = line.trim();
// 姓名
if (extractedData.get("name") == null) {
// 先尝试使用正则表达式匹配
java.util.regex.Matcher m = java.util.regex.Pattern.compile(namePattern).matcher(line);
if (m.find()) {
String name = m.group(1).replaceAll("\\s+", "");
if (name.contains("门诊号")) {
name = name.split("门诊号")[0];
}
extractedData.put("name", name);
} else {
// 如果正则匹配失败尝试直接提取
if (line.contains("姓名") || line.contains("姓名:") || line.contains("姓 名")) {
// 统一处理各种可能的姓名标识
String processedLine = line.replaceAll("\\s*名\\s*[:]?", "姓名:");
String[] parts = processedLine.split("姓名:");
if (parts.length > 1) {
String afterName = parts[1].trim();
// 找到下一个字段的位置
int nextFieldIndex = -1;
if (afterName.contains("门诊号") || afterName.contains("门 诊 号")) {
nextFieldIndex = afterName.indexOf("门诊号");
if (nextFieldIndex == -1) {
nextFieldIndex = afterName.indexOf("门 诊 号");
}
} else if (afterName.contains("性别") || afterName.contains("性 别")) {
nextFieldIndex = afterName.indexOf("性别");
if (nextFieldIndex == -1) {
nextFieldIndex = afterName.indexOf("性 别");
}
}
if (nextFieldIndex > 0) {
String name = afterName.substring(0, nextFieldIndex)
.replaceAll("[:]", "")
.replaceAll("\\s+", "")
.trim();
extractedData.put("name", name);
}
}
}
}
}
// 性别
if (extractedData.get("gender") == null) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile(genderPattern).matcher(line);
if (m.find()) {
extractedData.put("gender", m.group(1));
}
}
// 年龄
if (extractedData.get("age") == null) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile(agePattern).matcher(line);
if (m.find()) {
extractedData.put("age", m.group(1));
}
}
// ID
if (extractedData.get("examId") == null) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile(idPattern).matcher(line);
if (m.find()) {
extractedData.put("examId", m.group(1));
}
}
}
// 2. 参数区底部1/3适配新模板
int paramStartY = (int) (height * 0.81);
int paramHeight = height - paramStartY;
BufferedImage paramArea = image.getSubimage(0, paramStartY, width, paramHeight);
String paramOcr = tesseract.doOCR(paramArea);
String[] paramLines = paramOcr.split("\\r?\\n");
String hrPattern = "心率[:]?\\s*([\\dOo./]+)";
String pPattern = "P时限[:]?\\s*([\\dOo./]+)";
String prPattern = "PR间期[:]?\\s*([\\dOo./]+)";
String qrsPattern = "QRS时限[:]?\\s*([\\dOo./]+)";
String qtPattern = "[@Q]T\\s*间\\s*期\\s*[:]?\\s*(\\d+)\\s*[mM][sS]";
String qtcPattern = "[@Q]Tc\\s*间\\s*期\\s*[:]?\\s*(\\d+)\\s*[mM][sS]";
String pAxlePattern = "P轴[:]?\\s*([\\dOo.]+)";
String qrsAxlePattern = "QRS轴[:]?\\s*([\\dOo.]+)";
String tAxlePattern = "T轴[:]?\\s*([\\dOo.]+)";
String rv5sv1Pattern = "RV5/SV1[:]?\\s*([\\dOo./]+)";
String rv5plusSv1Pattern = "RV5\\+SV1[:]?\\s*([\\dOo./]+)";
// 用于存储QT和QTc的值
String qtValue = null;
String qtcValue = null;
// 用于存储三个电轴的值
String pAxleValue = null;
String qrsAxleValue = null;
String tAxleValue = null;
for (String line : paramLines) {
line = line.replaceAll("\\s+", "").trim();
// HR
if (extractedData.get("hr") == null) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile(hrPattern).matcher(line);
if (m.find()) {
String hrValue = m.group(1).replaceAll("[Oo]", "0");
extractedData.put("hr", hrValue);
}
}
// P
if (extractedData.get("P") == null) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile(pPattern).matcher(line);
if (m.find()) {
String pValue = m.group(1).replaceAll("[Oo]", "0");
extractedData.put("P", pValue);
}
}
// PR
if (extractedData.get("pr") == null) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile(prPattern).matcher(line);
if (m.find()) {
extractedData.put("pr", m.group(1).replaceAll("[Oo]", "0"));
}
}
// QRS
if (extractedData.get("qrs") == null) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile(qrsPattern).matcher(line);
if (m.find()) {
extractedData.put("qrs", m.group(1).replaceAll("[Oo]", "0"));
}
}
// QT
if (qtValue == null) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile(qtPattern).matcher(line);
if (m.find()) {
qtValue = m.group(1).replaceAll("[Oo]", "0");
}
}
// QTc
if (qtcValue == null) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile(qtcPattern).matcher(line);
if (m.find()) {
qtcValue = m.group(1).replaceAll("[Oo]", "0");
}
}
// P轴
if (pAxleValue == null) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile(pAxlePattern).matcher(line);
if (m.find()) {
pAxleValue = m.group(1).replaceAll("[Oo]", "0");
}
}
// QRS轴
if (qrsAxleValue == null) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile(qrsAxlePattern).matcher(line);
if (m.find()) {
qrsAxleValue = m.group(1).replaceAll("[Oo]", "0");
}
}
// T轴
if (tAxleValue == null) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile(tAxlePattern).matcher(line);
if (m.find()) {
tAxleValue = m.group(1).replaceAll("[Oo]", "0");
}
}
// RV5/SV1
if (extractedData.get("rv5/sv1") == null) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile(rv5sv1Pattern).matcher(line);
if (m.find()) {
extractedData.put("rv5/sv1", m.group(1).replaceAll("[Oo]", "0"));
}
}
// RV5+SV1
if (extractedData.get("rv5Sv1") == null) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile(rv5plusSv1Pattern).matcher(line);
if (m.find()) {
extractedData.put("rv5Sv1", m.group(1).replaceAll("[Oo]", "0"));
}
}
}
// 处理QT/QTc的值
if (qtValue != null || qtcValue != null) {
if (qtValue != null && qtcValue != null) {
extractedData.put("qt/qtc", qtValue + "/" + qtcValue);
} else if (qtValue != null) {
extractedData.put("qt/qtc", qtValue);
} else if (qtcValue != null) {
extractedData.put("qt/qtc", qtcValue);
}
}
// 处理三个电轴的值
if (pAxleValue != null || qrsAxleValue != null || tAxleValue != null) {
StringBuilder axleValue = new StringBuilder();
if (pAxleValue != null) {
axleValue.append(pAxleValue);
}
if (qrsAxleValue != null) {
if (axleValue.length() > 0) {
axleValue.append("/");
}
axleValue.append(qrsAxleValue);
}
if (tAxleValue != null) {
if (axleValue.length() > 0) {
axleValue.append("/");
}
axleValue.append(tAxleValue);
}
extractedData.put("pAxle/qrsAxle/tAxle", axleValue.toString());
}
// 3. 底部区域提取检查时间底部5%
int bottomHeight = (int) (height * 0.05);
int bottomStartY = height - bottomHeight;
BufferedImage bottomArea = image.getSubimage(0, bottomStartY, width, bottomHeight);
String bottomOcr = tesseract.doOCR(bottomArea);
String[] bottomLines = bottomOcr.split("\\r?\\n");
for (String line : bottomLines) {
String lineNoSpace = line.replaceAll("\\s+", "");
if (extractedData.get("collectionTime") == null) {
java.util.regex.Matcher m = java.util.regex.Pattern.compile("日期[:]?(\\d{4}-\\d{2}-\\d{2})").matcher(lineNoSpace);
if (m.find()) {
extractedData.put("collectionTime", m.group(1));
}
}
}
} catch (Exception e) {
logger.error("processImageWithLQXSD 识别异常", e);
}
return extractedData;
}
/**
* 关闭资源
*/