处理礼泉县城关卫生院ocr识别 字段不对应问题 新增LQXSD 方法
This commit is contained in:
parent
9a29647a42
commit
e636f0d273
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭资源
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user