u
This commit is contained in:
1 parent
a96f04630e
commit
7837b87959
27 files changed
+508
-894
No files matched your search
@@ -1,6 +1,46 @@
|
||||
package com.email;
|
||||
|
||||
import com.email.core.fetch.EmailFetcher;
|
||||
import com.email.core.fetch.ImapJavaMailEmailFetcher;
|
||||
import com.email.domain.entity.UserAccount;
|
||||
|
||||
import javax.mail.*;
|
||||
import javax.mail.Flags;
|
||||
import javax.mail.search.FlagTerm;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import java.io.*;
|
||||
import java.util.Properties;
|
||||
|
||||
public class Test {
|
||||
public static void main(String[] args) throws Exception {
|
||||
UserAccount userAccount = new UserAccount();
|
||||
userAccount.setEmail("717406575@qq.com");
|
||||
userAccount.setPassword("dhqesrwzgblrbcac");
|
||||
userAccount.setImapHost("imap.qq.com");
|
||||
userAccount.setImapPort("993");
|
||||
|
||||
EmailFetcher emailFetcher = new ImapJavaMailEmailFetcher();
|
||||
|
||||
emailFetcher.fetchAll(
|
||||
userAccount,
|
||||
|
||||
// progressConsumer: 打印进度
|
||||
progress -> System.out.printf("📩 [%s] 已拉取 %d / %d 封邮件%n",
|
||||
progress.getFolderName(),
|
||||
progress.getCurrent(),
|
||||
progress.getTotal()
|
||||
),
|
||||
|
||||
// folderConsumer: 开始处理某个文件夹
|
||||
folder -> {
|
||||
|
||||
},
|
||||
|
||||
// fetchDataConsumer: 每封邮件拉取完成后处理
|
||||
emailData -> {
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ public class EmailImapClient {
|
||||
props.put("mail.imaps.partialfetch", "false");
|
||||
|
||||
|
||||
// 在连接参数中强制指定ID信息
|
||||
// 在连接参数中强制指定ID信息
|
||||
props.put("mail.imap.id.mechanism", "OAUTH2");
|
||||
props.put("mail.imap.id.name", "your_client_name");
|
||||
props.put("mail.imap.id.version", "1.0.0");
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.email.client;
|
||||
|
||||
import com.email.domain.entity.UserAccount;
|
||||
|
||||
import javax.mail.Session;
|
||||
import java.util.HashMap;
|
||||
import java.util.Properties;
|
||||
|
||||
public class EmailImapClient2 {
|
||||
private UserAccount userAccount;
|
||||
|
||||
public void connect(){
|
||||
Properties props = new Properties();
|
||||
props.put("mail.store.protocol", "imap");
|
||||
props.put("mail.imap.host", userAccount.getImapHost());
|
||||
props.put("mail.imap.port", userAccount.getImapPort());
|
||||
props.put("mail.imap.ssl.enable", "true");
|
||||
props.put("mail.imap.starttls.enable", "true");
|
||||
props.put("mail.imap.partialfetch", "false");
|
||||
props.put("mail.imaps.partialfetch", "false");
|
||||
|
||||
|
||||
// 在连接参数中强制指定ID信息
|
||||
props.put("mail.imap.id.mechanism", "OAUTH2");
|
||||
props.put("mail.imap.id.name", userAccount.getDisplayName());
|
||||
props.put("mail.imap.id.version", "1.0.0");
|
||||
|
||||
props.put("mail.imap.fetchsize", "4194304");
|
||||
HashMap<String, String> imapId = new HashMap<>();
|
||||
imapId.put("name", String.valueOf(userAccount.getId()));
|
||||
imapId.put("version", "1.0.0");
|
||||
imapId.put("vendor", "vendor");
|
||||
imapId.put("support-email", userAccount.getEmail());
|
||||
Session.getInstance(props);
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.email.client;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
|
||||
public class ImapUtf7 {
|
||||
public static String decode(String encoded) {
|
||||
if (encoded == null) return null;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int i = 0;
|
||||
while (i < encoded.length()) {
|
||||
char ch = encoded.charAt(i);
|
||||
if (ch == '&') {
|
||||
int start = ++i;
|
||||
while (i < encoded.length() && encoded.charAt(i) != '-') {
|
||||
i++;
|
||||
}
|
||||
if (i == start) {
|
||||
sb.append('&');
|
||||
i++; // 跳过 '-'
|
||||
} else {
|
||||
String base64 = encoded.substring(start, i).replace(',', '/');
|
||||
byte[] utf16Bytes = Base64.getDecoder().decode(base64);
|
||||
sb.append(new String(utf16Bytes, StandardCharsets.UTF_16BE));
|
||||
i++; // 跳过 '-'
|
||||
}
|
||||
} else {
|
||||
sb.append(ch);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.email.core.fetch;
|
||||
|
||||
import com.email.core.fetch.model.EmailFetchData;
|
||||
import com.email.core.fetch.model.EmailFetchProgress;
|
||||
import com.email.domain.entity.EmailFolder;
|
||||
import com.email.domain.entity.UserAccount;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public interface EmailFetcher {
|
||||
void fetchAll(UserAccount userAccount,
|
||||
Consumer<EmailFetchProgress> emailFetchProgressConsumer,
|
||||
Consumer<EmailFolder> emailFolderConsumer,
|
||||
Consumer<EmailFetchData> emailFetchDataConsumer);
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package com.email.core.fetch;
|
||||
|
||||
public class ImapCommandEmailFetcher {
|
||||
}
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
package com.email.core.fetch;
|
||||
|
||||
import com.email.constants.ResponseStatusConstants;
|
||||
import com.email.core.fetch.model.EmailFetchData;
|
||||
import com.email.core.fetch.model.EmailFetchProgress;
|
||||
import com.email.domain.entity.EmailFolder;
|
||||
import com.email.domain.entity.UserAccount;
|
||||
import com.email.enums.ResponseEnum;
|
||||
import com.email.exception.auth.AuthException;
|
||||
import com.sun.javaws.progress.Progress;
|
||||
import com.sun.mail.imap.IMAPFolder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.mail.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Slf4j
|
||||
public class ImapJavaMailEmailFetcher implements EmailFetcher {
|
||||
|
||||
private final ExecutorService folderExecutor = Executors.newFixedThreadPool(10);
|
||||
|
||||
|
||||
@Override
|
||||
public void fetchAll(UserAccount userAccount, Consumer<EmailFetchProgress> progressConsumer, Consumer<EmailFolder> folderConsumer, Consumer<EmailFetchData> fetchDataConsumer) {
|
||||
Store store = null;
|
||||
try {
|
||||
store = connect(userAccount); // connect 内部已处理异常
|
||||
|
||||
List<Folder> allFolders = listAllFolders(store.getDefaultFolder());
|
||||
|
||||
CountDownLatch folderLatch = new CountDownLatch(allFolders.size());
|
||||
|
||||
for (Folder folder : allFolders) {
|
||||
folderExecutor.submit(() -> {
|
||||
try {
|
||||
processFolder(folder, progressConsumer, folderConsumer, fetchDataConsumer);
|
||||
} catch (Exception e) {
|
||||
log.error("处理文件夹 [{}] 失败:{}", folder.getFullName(), e.getMessage(), e);
|
||||
} finally {
|
||||
folderLatch.countDown();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
folderLatch.await(); // 等待所有文件夹处理完
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("抓取邮件失败:" + e.getMessage(), e);
|
||||
} finally {
|
||||
if (store != null && store.isConnected()) {
|
||||
try {
|
||||
store.close();
|
||||
} catch (MessagingException closeEx) {
|
||||
log.warn("关闭邮箱连接时异常:{}", closeEx.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 递归获取所有文件夹(包括子文件夹)
|
||||
private List<Folder> listAllFolders(Folder folder) throws MessagingException {
|
||||
List<Folder> allFolders = new ArrayList<>();
|
||||
|
||||
if ((folder.getType() & Folder.HOLDS_MESSAGES) != 0) {
|
||||
allFolders.add(folder);
|
||||
}
|
||||
|
||||
if ((folder.getType() & Folder.HOLDS_FOLDERS) != 0) {
|
||||
Folder[] subFolders = folder.list();
|
||||
for (Folder sub : subFolders) {
|
||||
allFolders.addAll(listAllFolders(sub));
|
||||
}
|
||||
}
|
||||
return allFolders;
|
||||
}
|
||||
|
||||
private void processFolder(Folder folder,
|
||||
Consumer<EmailFetchProgress> progressConsumer,
|
||||
Consumer<EmailFolder> folderConsumer,
|
||||
Consumer<EmailFetchData> fetchDataConsumer) throws Exception {
|
||||
if (!(folder instanceof IMAPFolder)) return;
|
||||
|
||||
folder.open(Folder.READ_ONLY);
|
||||
|
||||
int totalMessages = folder.getMessageCount();
|
||||
if (totalMessages == 0) {
|
||||
folder.close(false);
|
||||
return;
|
||||
}
|
||||
|
||||
EmailFolder emailFolder = new EmailFolder();
|
||||
|
||||
folderConsumer.accept(emailFolder);
|
||||
|
||||
FetchProfile fetchProfile = new FetchProfile();
|
||||
fetchProfile.add(FetchProfile.Item.ENVELOPE);
|
||||
fetchProfile.add(FetchProfile.Item.CONTENT_INFO);
|
||||
|
||||
Message[] messages = folder.getMessages();
|
||||
folder.fetch(messages, fetchProfile);
|
||||
|
||||
for (int i = 0; i < messages.length; i++) {
|
||||
Message message = messages[i];
|
||||
try {
|
||||
progressConsumer.accept(new EmailFetchProgress(folder.getFullName(), i + 1, totalMessages));
|
||||
} catch (Exception e) {
|
||||
log.warn("处理邮件失败 folder={} index={} error={}", folder.getFullName(), i, e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
folder.close(false);
|
||||
}
|
||||
|
||||
private Store connect(UserAccount account) {
|
||||
Properties props = new Properties();
|
||||
props.put("mail.store.protocol", "imaps");
|
||||
props.put("mail.imap.ssl.enable", "true");
|
||||
props.put("mail.imap.connectiontimeout", "10000");
|
||||
props.put("mail.imap.timeout", "10000");
|
||||
|
||||
try {
|
||||
Session session = Session.getInstance(props);
|
||||
Store store = session.getStore("imaps");
|
||||
|
||||
store.connect(
|
||||
account.getImapHost(),
|
||||
Integer.parseInt(account.getImapPort()),
|
||||
account.getEmail(),
|
||||
account.getPassword()
|
||||
);
|
||||
|
||||
return store;
|
||||
} catch (AuthenticationFailedException e) {
|
||||
log.warn("邮箱认证失败:账号={},原因={}", account.getEmail(), e.getMessage(), e);
|
||||
throw new AuthException(ResponseEnum.AUTH_EMAIL_INVALID_CREDENTIALS);
|
||||
} catch (NoSuchProviderException e) {
|
||||
log.warn("邮箱协议不支持:账号={},原因={}", account.getEmail(), e.getMessage(), e);
|
||||
throw new AuthException(ResponseEnum.AUTH_EMAIL_PROTOCOL_UNSUPPORTED);
|
||||
} catch (MessagingException e) {
|
||||
log.warn("邮箱服务器连接失败:账号={},Host={},Port={},SSL={},原因={}",
|
||||
account.getEmail(),
|
||||
account.getImapHost(),
|
||||
account.getImapPort(),
|
||||
account.getImapSsl(),
|
||||
e.getMessage(),
|
||||
e
|
||||
);
|
||||
throw new AuthException(ResponseEnum.AUTH_EMAIL_CONNECTION_FAILED);
|
||||
} catch (Exception e) {
|
||||
log.error("邮箱连接发生未知错误:账号={},原因={}", account.getEmail(), e.getMessage(), e);
|
||||
throw new AuthException(ResponseEnum.AUTH_EMAIL_UNKNOWN_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.email.core.fetch.model;
|
||||
|
||||
import com.email.domain.entity.EmailAddress;
|
||||
import com.email.domain.entity.EmailFile;
|
||||
import com.email.domain.entity.EmailSummary;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class EmailFetchData {
|
||||
private EmailSummary emailSummary;
|
||||
private List<EmailAddress> emailAddressList;
|
||||
private List<EmailFile> emailFileList;
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.email.core.fetch.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class EmailFetchProgress {
|
||||
private String folderName; // 文件夹名称
|
||||
|
||||
private Integer current; // 当前页
|
||||
private Integer total; // 总数
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.email.core.send;
|
||||
|
||||
public interface EmailSender {
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package com.email.core.send;
|
||||
|
||||
public class SmtpCommandEmailSender {
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package com.email.core.send;
|
||||
|
||||
public class SmtpJavaMailEmailSender {
|
||||
}
|
||||
@@ -19,7 +19,7 @@ public class EmailSentDTO {
|
||||
|
||||
private String body; // 邮件正文内容
|
||||
private String from; // 发件人
|
||||
private String fromName; // 发件人
|
||||
private String fromName; // 发件人名称
|
||||
|
||||
private Integer isSingSent; // 是否群发单显(1 是,0 否)
|
||||
private Integer isHtml;
|
||||
|
||||
@@ -15,14 +15,14 @@ import lombok.experimental.Accessors;
|
||||
@NoArgsConstructor
|
||||
@TableName("email_file")
|
||||
@Accessors(chain = true)
|
||||
public class EmailFile {
|
||||
public class EmailFile {
|
||||
@TableId
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id; // 主键ID
|
||||
private String fileName; // 文件名(不含路径)
|
||||
private String fileExtension; // 文件扩展名,例如:jpg、pdf
|
||||
private Long fileSize; // 文件大小,单位字节
|
||||
private String filePath; // 文件路径(建议存相对路径)
|
||||
private String filePath; // 文件路径(相对路径)
|
||||
private Integer fileType; // 文件类型:0-临时,1-附件,2-内嵌资源,3-模板等
|
||||
|
||||
private Long emailId; // 关联的邮件ID
|
||||
@@ -31,4 +31,3 @@ public class EmailFile {
|
||||
@TableField(exist = false)
|
||||
private String fileUrl;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,13 @@ public enum ResponseEnum {
|
||||
AUTH_SMTP_PROTOCOL_ERROR(ResponseStatusConstants.UNAUTHORIZED, "SMTP 协议不支持或配置错误"),
|
||||
AUTH_IMAP_PROTOCOL_ERROR(ResponseStatusConstants.UNAUTHORIZED, "IMAP 协议不支持或配置错误"),
|
||||
AUTH_SERVER_CONNECTION_FAILED(ResponseStatusConstants.UNAUTHORIZED, "邮箱服务器连接失败,请检查是否已经开通 IMAP/SMTP 协议"),
|
||||
AUTH_UNKNOWN_ERROR(ResponseStatusConstants.UNAUTHORIZED,"邮箱服务器连接失败,请重新登录");
|
||||
AUTH_UNKNOWN_ERROR(ResponseStatusConstants.UNAUTHORIZED,"邮箱服务器连接失败,请重新登录"),
|
||||
|
||||
AUTH_EMAIL_INVALID_CREDENTIALS(ResponseStatusConstants.UNAUTHORIZED,"邮箱账户或密码错误"),
|
||||
AUTH_EMAIL_PROTOCOL_UNSUPPORTED(ResponseStatusConstants.UNAUTHORIZED,"邮箱协议不支持"),
|
||||
AUTH_EMAIL_CONNECTION_FAILED(ResponseStatusConstants.UNAUTHORIZED,"邮箱服务器连接失败,请检查配置"),
|
||||
AUTH_EMAIL_UNKNOWN_ERROR(ResponseStatusConstants.UNAUTHORIZED,"连接邮箱时发生未知错误");
|
||||
|
||||
|
||||
private final Integer code; //响应码
|
||||
private final String message; //相应信息
|
||||
|
||||
Whitespace-only changes.
Binary file not shown.
|
Before Width: | Height: | Size: 77 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 90 KiB |
@@ -1,663 +0,0 @@
|
||||
# 识别结果
|
||||
|
||||
参数基本采用默认参数,都训练 **10轮** 。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## PP-OCRv5_server (极好)
|
||||
|
||||
识别效果:**极好** ,基本都是别出来了,并且正确。
|
||||
|
||||

|
||||
|
||||
### PP-OCRv5_server_det.yml
|
||||
|
||||
```yaml
|
||||
Global:
|
||||
model_name: PP-OCRv5_server_det # To use static model for inference.
|
||||
debug: false
|
||||
use_gpu: true
|
||||
epoch_num: &epoch_num 10
|
||||
log_smooth_window: 20
|
||||
print_batch_step: 10
|
||||
save_model_dir: ./output-v5server/PP-OCRv5_server_det
|
||||
save_epoch_step: 200
|
||||
eval_batch_step:
|
||||
- 0
|
||||
- 200
|
||||
cal_metric_during_train: false
|
||||
checkpoints:
|
||||
pretrained_model: ./pretrain_models/PP-OCRv5_server_det_pretrained.pdparams
|
||||
save_inference_dir: null
|
||||
use_visualdl: false
|
||||
infer_img: doc/imgs_en/img_10.jpg
|
||||
save_res_path: ./checkpoints/det_db/predicts_db.txt
|
||||
distributed: false
|
||||
|
||||
Architecture:
|
||||
model_type: det
|
||||
algorithm: DB
|
||||
Transform: null
|
||||
Backbone:
|
||||
name: PPHGNetV2_B4
|
||||
det: True
|
||||
Neck:
|
||||
name: LKPAN
|
||||
out_channels: 256
|
||||
intracl: true
|
||||
Head:
|
||||
name: PFHeadLocal
|
||||
k: 50
|
||||
mode: "large"
|
||||
|
||||
|
||||
Loss:
|
||||
name: DBLoss
|
||||
balance_loss: true
|
||||
main_loss_type: DiceLoss
|
||||
alpha: 5
|
||||
beta: 10
|
||||
ohem_ratio: 3
|
||||
|
||||
Optimizer:
|
||||
name: Adam
|
||||
beta1: 0.9
|
||||
beta2: 0.999
|
||||
lr:
|
||||
name: Cosine
|
||||
learning_rate: 0.001 #(8*8c)
|
||||
warmup_epoch: 2
|
||||
regularizer:
|
||||
name: L2
|
||||
factor: 1e-6
|
||||
|
||||
PostProcess:
|
||||
name: DBPostProcess
|
||||
thresh: 0.3
|
||||
box_thresh: 0.6
|
||||
max_candidates: 1000
|
||||
unclip_ratio: 1.5
|
||||
|
||||
Metric:
|
||||
name: DetMetric
|
||||
main_indicator: hmean
|
||||
|
||||
Train:
|
||||
dataset:
|
||||
name: SimpleDataSet
|
||||
data_dir: ./data/input0/images #图片文件夹路径
|
||||
label_file_list:
|
||||
- ./det_train_label.txt #标签路径
|
||||
ratio_list: [1.0]
|
||||
transforms:
|
||||
- DecodeImage:
|
||||
img_mode: BGR
|
||||
channel_first: false
|
||||
- DetLabelEncode: null
|
||||
- CopyPaste: null
|
||||
- IaaAugment:
|
||||
augmenter_args:
|
||||
- type: Fliplr
|
||||
args:
|
||||
p: 0.5
|
||||
- type: Affine
|
||||
args:
|
||||
rotate:
|
||||
- -10
|
||||
- 10
|
||||
- type: Resize
|
||||
args:
|
||||
size:
|
||||
- 0.5
|
||||
- 3
|
||||
- EastRandomCropData:
|
||||
size:
|
||||
- 640
|
||||
- 640
|
||||
max_tries: 50
|
||||
keep_ratio: true
|
||||
- MakeBorderMap:
|
||||
shrink_ratio: 0.4
|
||||
thresh_min: 0.3
|
||||
thresh_max: 0.7
|
||||
total_epoch: *epoch_num
|
||||
- MakeShrinkMap:
|
||||
shrink_ratio: 0.4
|
||||
min_text_size: 8
|
||||
total_epoch: *epoch_num
|
||||
- NormalizeImage:
|
||||
scale: 1./255.
|
||||
mean:
|
||||
- 0.485
|
||||
- 0.456
|
||||
- 0.406
|
||||
std:
|
||||
- 0.229
|
||||
- 0.224
|
||||
- 0.225
|
||||
order: hwc
|
||||
- ToCHWImage: null
|
||||
- KeepKeys:
|
||||
keep_keys:
|
||||
- image
|
||||
- threshold_map
|
||||
- threshold_mask
|
||||
- shrink_map
|
||||
- shrink_mask
|
||||
loader:
|
||||
shuffle: true
|
||||
drop_last: false
|
||||
batch_size_per_card: 10
|
||||
num_workers: 1
|
||||
|
||||
Eval:
|
||||
dataset:
|
||||
name: SimpleDataSet
|
||||
data_dir: ./data/input0/images
|
||||
label_file_list:
|
||||
- ./det_eval_label.txt
|
||||
transforms:
|
||||
- DecodeImage:
|
||||
img_mode: BGR
|
||||
channel_first: false
|
||||
- DetLabelEncode: null
|
||||
- DetResizeForTest:
|
||||
- NormalizeImage:
|
||||
scale: 1./255.
|
||||
mean:
|
||||
- 0.485
|
||||
- 0.456
|
||||
- 0.406
|
||||
std:
|
||||
- 0.229
|
||||
- 0.224
|
||||
- 0.225
|
||||
order: hwc
|
||||
- ToCHWImage: null
|
||||
- KeepKeys:
|
||||
keep_keys:
|
||||
- image
|
||||
- shape
|
||||
- polys
|
||||
- ignore_tags
|
||||
loader:
|
||||
shuffle: false
|
||||
drop_last: false
|
||||
batch_size_per_card: 1
|
||||
num_workers: 1
|
||||
profiler_options: null
|
||||
```
|
||||
|
||||
### PP-OCRv5_server_rec.yml
|
||||
|
||||
```yaml
|
||||
Global:
|
||||
model_name: PP-OCRv5_server_rec # To use static model for inference.
|
||||
debug: false
|
||||
use_gpu: true
|
||||
epoch_num: 10
|
||||
log_smooth_window: 20
|
||||
print_batch_step: 10
|
||||
save_model_dir: ./output-v5server/PP-OCRv5_server_rec
|
||||
save_epoch_step: 200
|
||||
eval_batch_step: [0, 200]
|
||||
cal_metric_during_train: true
|
||||
calc_epoch_interval: 1
|
||||
pretrained_model: ./pretrain_models/PP-OCRv5_server_rec_pretrained.pdparams
|
||||
checkpoints:
|
||||
save_inference_dir:
|
||||
use_visualdl: false
|
||||
infer_img: doc/imgs_words/ch/word_1.jpg
|
||||
character_dict_path: ./ppocr/utils/dict/ppocrv5_dict.txt
|
||||
max_text_length: &max_text_length 25
|
||||
infer_mode: false
|
||||
use_space_char: true
|
||||
distributed: true
|
||||
save_res_path: ./output-v5server/rec/predicts_ppocrv5.txt
|
||||
d2s_train_image_shape: [3, 48, 320]
|
||||
|
||||
|
||||
Optimizer:
|
||||
name: Adam
|
||||
beta1: 0.9
|
||||
beta2: 0.999
|
||||
lr:
|
||||
name: Cosine
|
||||
learning_rate: 0.0005
|
||||
warmup_epoch: 1
|
||||
regularizer:
|
||||
name: L2
|
||||
factor: 3.0e-05
|
||||
|
||||
|
||||
Architecture:
|
||||
model_type: rec
|
||||
algorithm: SVTR_HGNet
|
||||
Transform:
|
||||
Backbone:
|
||||
name: PPHGNetV2_B4
|
||||
text_rec: True
|
||||
Head:
|
||||
name: MultiHead
|
||||
head_list:
|
||||
- CTCHead:
|
||||
Neck:
|
||||
name: svtr
|
||||
dims: 120
|
||||
depth: 2
|
||||
hidden_dims: 120
|
||||
kernel_size: [1, 3]
|
||||
use_guide: True
|
||||
Head:
|
||||
fc_decay: 0.00001
|
||||
- NRTRHead:
|
||||
nrtr_dim: 384
|
||||
max_text_length: *max_text_length
|
||||
|
||||
Loss:
|
||||
name: MultiLoss
|
||||
loss_config_list:
|
||||
- CTCLoss:
|
||||
- NRTRLoss:
|
||||
|
||||
PostProcess:
|
||||
name: CTCLabelDecode
|
||||
|
||||
Metric:
|
||||
name: RecMetric
|
||||
main_indicator: acc
|
||||
|
||||
Train:
|
||||
dataset:
|
||||
name: MultiScaleDataSet
|
||||
ds_width: false
|
||||
data_dir: ./RecTrainData/
|
||||
ext_op_transform_idx: 1
|
||||
label_file_list:
|
||||
- ./rec_train_label.txt
|
||||
transforms:
|
||||
- DecodeImage:
|
||||
img_mode: BGR
|
||||
channel_first: false
|
||||
- RecAug:
|
||||
- MultiLabelEncode:
|
||||
gtc_encode: NRTRLabelEncode
|
||||
- KeepKeys:
|
||||
keep_keys:
|
||||
- image
|
||||
- label_ctc
|
||||
- label_gtc
|
||||
- length
|
||||
- valid_ratio
|
||||
sampler:
|
||||
name: MultiScaleSampler
|
||||
scales: [[320, 32], [320, 48], [320, 64]]
|
||||
first_bs: &bs 12
|
||||
fix_bs: false
|
||||
divided_factor: [8, 16] # w, h
|
||||
is_training: True
|
||||
loader:
|
||||
shuffle: true
|
||||
batch_size_per_card: 10
|
||||
drop_last: true
|
||||
num_workers: 1
|
||||
Eval:
|
||||
dataset:
|
||||
name: SimpleDataSet
|
||||
data_dir: ./RecEvalData/
|
||||
label_file_list:
|
||||
- ./rec_eval_label.txt
|
||||
transforms:
|
||||
- DecodeImage:
|
||||
img_mode: BGR
|
||||
channel_first: false
|
||||
- MultiLabelEncode:
|
||||
gtc_encode: NRTRLabelEncode
|
||||
- RecResizeImg:
|
||||
image_shape: [3, 48, 320]
|
||||
- KeepKeys:
|
||||
keep_keys:
|
||||
- image
|
||||
- label_ctc
|
||||
- label_gtc
|
||||
- length
|
||||
- valid_ratio
|
||||
loader:
|
||||
shuffle: false
|
||||
drop_last: false
|
||||
batch_size_per_card: 1
|
||||
num_workers: 1
|
||||
```
|
||||
|
||||
|
||||
|
||||
## PP-OCRv5_mobile
|
||||
|
||||
### PP-OCRv5_mobile_det.yml
|
||||
|
||||
```yaml
|
||||
Global:
|
||||
model_name: PP-OCRv5_mobile_det # To use static model for inference.
|
||||
debug: false
|
||||
use_gpu: true
|
||||
epoch_num: &epoch_num 100
|
||||
log_smooth_window: 20
|
||||
print_batch_step: 100
|
||||
save_model_dir: ./output-v5mobile/PP-OCRv5_mobile_det
|
||||
save_epoch_step: 200
|
||||
eval_batch_step:
|
||||
- 0
|
||||
- 200
|
||||
cal_metric_during_train: false
|
||||
checkpoints:
|
||||
pretrained_model: https://paddleocr.bj.bcebos.com/pretrained/PPLCNetV3_x0_75_ocr_det.pdparams
|
||||
save_inference_dir: null
|
||||
use_visualdl: false
|
||||
infer_img: doc/imgs_en/img_10.jpg
|
||||
save_res_path: ./checkpoints/det_db/predicts_db.txt
|
||||
d2s_train_image_shape: [3, 640, 640]
|
||||
distributed: true
|
||||
|
||||
Architecture:
|
||||
model_type: det
|
||||
algorithm: DB
|
||||
Transform: null
|
||||
Backbone:
|
||||
name: PPLCNetV3
|
||||
scale: 0.75
|
||||
det: True
|
||||
Neck:
|
||||
name: RSEFPN
|
||||
out_channels: 96
|
||||
shortcut: True
|
||||
Head:
|
||||
name: DBHead
|
||||
k: 50
|
||||
fix_nan: True
|
||||
|
||||
Loss:
|
||||
name: DBLoss
|
||||
balance_loss: true
|
||||
main_loss_type: DiceLoss
|
||||
alpha: 5
|
||||
beta: 10
|
||||
ohem_ratio: 3
|
||||
|
||||
Optimizer:
|
||||
name: Adam
|
||||
beta1: 0.9
|
||||
beta2: 0.999
|
||||
lr:
|
||||
name: Cosine
|
||||
learning_rate: 0.001 #(8*8c)
|
||||
warmup_epoch: 2
|
||||
regularizer:
|
||||
name: L2
|
||||
factor: 5.0e-05
|
||||
|
||||
PostProcess:
|
||||
name: DBPostProcess
|
||||
thresh: 0.3
|
||||
box_thresh: 0.6
|
||||
max_candidates: 1000
|
||||
unclip_ratio: 1.5
|
||||
|
||||
Metric:
|
||||
name: DetMetric
|
||||
main_indicator: hmean
|
||||
|
||||
Train:
|
||||
dataset:
|
||||
name: SimpleDataSet
|
||||
data_dir: ./data/input0/images #图片文件夹路径
|
||||
label_file_list:
|
||||
- ./det_train_label.txt #标签路径
|
||||
ratio_list: [1.0]
|
||||
transforms:
|
||||
- DecodeImage:
|
||||
img_mode: BGR
|
||||
channel_first: false
|
||||
- DetLabelEncode: null
|
||||
- CopyPaste: null
|
||||
- IaaAugment:
|
||||
augmenter_args:
|
||||
- type: Fliplr
|
||||
args:
|
||||
p: 0.5
|
||||
- type: Affine
|
||||
args:
|
||||
rotate:
|
||||
- -10
|
||||
- 10
|
||||
- type: Resize
|
||||
args:
|
||||
size:
|
||||
- 0.5
|
||||
- 3
|
||||
- EastRandomCropData:
|
||||
size:
|
||||
- 640
|
||||
- 640
|
||||
max_tries: 50
|
||||
keep_ratio: true
|
||||
- MakeBorderMap:
|
||||
shrink_ratio: 0.4
|
||||
thresh_min: 0.3
|
||||
thresh_max: 0.7
|
||||
total_epoch: *epoch_num
|
||||
- MakeShrinkMap:
|
||||
shrink_ratio: 0.4
|
||||
min_text_size: 8
|
||||
total_epoch: *epoch_num
|
||||
- NormalizeImage:
|
||||
scale: 1./255.
|
||||
mean:
|
||||
- 0.485
|
||||
- 0.456
|
||||
- 0.406
|
||||
std:
|
||||
- 0.229
|
||||
- 0.224
|
||||
- 0.225
|
||||
order: hwc
|
||||
- ToCHWImage: null
|
||||
- KeepKeys:
|
||||
keep_keys:
|
||||
- image
|
||||
- threshold_map
|
||||
- threshold_mask
|
||||
- shrink_map
|
||||
- shrink_mask
|
||||
loader:
|
||||
shuffle: true
|
||||
drop_last: false
|
||||
batch_size_per_card: 14
|
||||
num_workers: 1
|
||||
|
||||
Eval:
|
||||
dataset:
|
||||
name: SimpleDataSet
|
||||
data_dir: ./data/input0/images
|
||||
label_file_list:
|
||||
- ./det_eval_label.txt
|
||||
transforms:
|
||||
- DecodeImage:
|
||||
img_mode: BGR
|
||||
channel_first: false
|
||||
- DetLabelEncode: null
|
||||
- DetResizeForTest:
|
||||
- NormalizeImage:
|
||||
scale: 1./255.
|
||||
mean:
|
||||
- 0.485
|
||||
- 0.456
|
||||
- 0.406
|
||||
std:
|
||||
- 0.229
|
||||
- 0.224
|
||||
- 0.225
|
||||
order: hwc
|
||||
- ToCHWImage: null
|
||||
- KeepKeys:
|
||||
keep_keys:
|
||||
- image
|
||||
- shape
|
||||
- polys
|
||||
- ignore_tags
|
||||
loader:
|
||||
shuffle: false
|
||||
drop_last: false
|
||||
batch_size_per_card: 1
|
||||
num_workers: 1
|
||||
profiler_options: null
|
||||
```
|
||||
|
||||
|
||||
|
||||
### PP-OCRv5_mobile_rec.yml
|
||||
|
||||
```yaml
|
||||
Global:
|
||||
model_name: PP-OCRv5_mobile_rec # To use static model for inference.
|
||||
debug: false
|
||||
use_gpu: true
|
||||
epoch_num: 75
|
||||
log_smooth_window: 20
|
||||
print_batch_step: 10
|
||||
save_model_dir: ./output/PP-OCRv5_mobile_rec
|
||||
save_epoch_step: 10
|
||||
eval_batch_step: [0, 2000]
|
||||
cal_metric_during_train: true
|
||||
pretrained_model: https://paddle-model-ecology.bj.bcebos.com/paddlex/official_pretrained_model/PP-OCRv5_mobile_rec_pretrained.pdparams
|
||||
checkpoints:
|
||||
save_inference_dir:
|
||||
use_visualdl: false
|
||||
infer_img: doc/imgs_words/ch/word_1.jpg
|
||||
character_dict_path: ./ppocr/utils/dict/ppocrv5_dict.txt
|
||||
max_text_length: &max_text_length 25
|
||||
infer_mode: false
|
||||
use_space_char: true
|
||||
distributed: true
|
||||
save_res_path: ./output/rec/predicts_ppocrv5.txt
|
||||
d2s_train_image_shape: [3, 48, 320]
|
||||
|
||||
|
||||
Optimizer:
|
||||
name: Adam
|
||||
beta1: 0.9
|
||||
beta2: 0.999
|
||||
lr:
|
||||
name: Cosine
|
||||
learning_rate: 0.0005
|
||||
warmup_epoch: 5
|
||||
regularizer:
|
||||
name: L2
|
||||
factor: 3.0e-05
|
||||
|
||||
|
||||
Architecture:
|
||||
model_type: rec
|
||||
algorithm: SVTR_LCNet
|
||||
Transform:
|
||||
Backbone:
|
||||
name: PPLCNetV3
|
||||
scale: 0.95
|
||||
Head:
|
||||
name: MultiHead
|
||||
head_list:
|
||||
- CTCHead:
|
||||
Neck:
|
||||
name: svtr
|
||||
dims: 120
|
||||
depth: 2
|
||||
hidden_dims: 120
|
||||
kernel_size: [1, 3]
|
||||
use_guide: True
|
||||
Head:
|
||||
fc_decay: 0.00001
|
||||
- NRTRHead:
|
||||
nrtr_dim: 384
|
||||
max_text_length: *max_text_length
|
||||
|
||||
Loss:
|
||||
name: MultiLoss
|
||||
loss_config_list:
|
||||
- CTCLoss:
|
||||
- NRTRLoss:
|
||||
|
||||
PostProcess:
|
||||
name: CTCLabelDecode
|
||||
|
||||
Metric:
|
||||
name: RecMetric
|
||||
main_indicator: acc
|
||||
|
||||
Train:
|
||||
dataset:
|
||||
name: MultiScaleDataSet
|
||||
ds_width: false
|
||||
data_dir: ./RecTrainData/
|
||||
ext_op_transform_idx: 1
|
||||
label_file_list:
|
||||
- ./rec_train_label.txt
|
||||
transforms:
|
||||
- DecodeImage:
|
||||
img_mode: BGR
|
||||
channel_first: false
|
||||
- RecConAug:
|
||||
prob: 0.5
|
||||
ext_data_num: 2
|
||||
image_shape: [48, 320, 3]
|
||||
max_text_length: *max_text_length
|
||||
- RecAug:
|
||||
- MultiLabelEncode:
|
||||
gtc_encode: NRTRLabelEncode
|
||||
- KeepKeys:
|
||||
keep_keys:
|
||||
- image
|
||||
- label_ctc
|
||||
- label_gtc
|
||||
- length
|
||||
- valid_ratio
|
||||
sampler:
|
||||
name: MultiScaleSampler
|
||||
scales: [[320, 32], [320, 48], [320, 64]]
|
||||
first_bs: &bs 128
|
||||
fix_bs: false
|
||||
divided_factor: [8, 16] # w, h
|
||||
is_training: True
|
||||
loader:
|
||||
shuffle: true
|
||||
batch_size_per_card: 14
|
||||
drop_last: true
|
||||
num_workers: 1
|
||||
Eval:
|
||||
dataset:
|
||||
name: SimpleDataSet
|
||||
data_dir: ./RecEvalData/
|
||||
label_file_list:
|
||||
- ./rec_eval_label.txt
|
||||
transforms:
|
||||
- DecodeImage:
|
||||
img_mode: BGR
|
||||
channel_first: false
|
||||
- MultiLabelEncode:
|
||||
gtc_encode: NRTRLabelEncode
|
||||
- RecResizeImg:
|
||||
image_shape: [3, 48, 320]
|
||||
- KeepKeys:
|
||||
keep_keys:
|
||||
- image
|
||||
- label_ctc
|
||||
- label_gtc
|
||||
- length
|
||||
- valid_ratio
|
||||
loader:
|
||||
shuffle: false
|
||||
drop_last: false
|
||||
batch_size_per_card: 14
|
||||
num_workers: 1
|
||||
```
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 102 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 103 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 85 KiB |
File renamed without changes.
@@ -0,0 +1,193 @@
|
||||
注:这里以 **识别集装箱号** 为案例进行演示
|
||||
|
||||
# 相关网站
|
||||
|
||||
- paddlepaddle:https://www.paddlepaddle.org.cn/
|
||||
- github:https://github.com/PaddlePaddle/PaddleOCR/tree/main
|
||||
|
||||
|
||||
|
||||
# 1 环境配置
|
||||
|
||||
当前使用的是虚拟环境:
|
||||
|
||||
- python:3.11
|
||||
- paddlepaddle:3.1
|
||||
- paddleocr:3.1.0
|
||||
|
||||
## 1.1 安装paddlepaddle
|
||||
|
||||
网站:https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/develop/install/pip/linux-pip.html
|
||||
|
||||
需要注意自己的 CUDA 版本,不要过高即可,查看命令:
|
||||
|
||||
```bash
|
||||
nvidia-smi
|
||||
```
|
||||
|
||||
输出如下:
|
||||
|
||||
```
|
||||
+-----------------------------------------------------------------------------+
|
||||
| NVIDIA-SMI 525.105.17 Driver Version: 525.105.17 CUDA Version: 12.0 |
|
||||
|-------------------------------+----------------------+----------------------+
|
||||
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
|
||||
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|
||||
| | | MIG M. |
|
||||
|===============================+======================+======================|
|
||||
| 0 Tesla T4 On | 00000000:00:09.0 Off | 0 |
|
||||
| N/A 27C P8 8W / 70W | 4MiB / 15360MiB | 0% Default |
|
||||
| | | N/A |
|
||||
+-------------------------------+----------------------+----------------------+
|
||||
|
||||
+-----------------------------------------------------------------------------+
|
||||
| Processes: |
|
||||
| GPU GI CI PID Type Process name GPU Memory |
|
||||
| ID ID Usage |
|
||||
|=============================================================================|
|
||||
| No running processes found |
|
||||
+-----------------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
当前电脑的 CUDA 版本为 12.0,所以下载 小于等于 12.0版本的paddlepaddle 即可
|
||||
|
||||
```bash
|
||||
python -m pip install paddlepaddle-gpu==3.1.0 -i https://www.paddlepaddle.org.cn/packages/stable/cu118/
|
||||
```
|
||||
|
||||
检查是否安装成功:
|
||||
|
||||
```bash
|
||||
python -c "import paddle; paddle.utils.run_check()"
|
||||
```
|
||||
|
||||
输出以下内容即代表成功:
|
||||
|
||||
```
|
||||
(ocr) root@VM-0-80-ubuntu:/workspace# python -c "import paddle; paddle.utils.run_check()"
|
||||
/root/miniforge3/envs/ocr/lib/python3.11/site-packages/paddle/utils/cpp_extension/extension_utils.py:715: UserWarning: No ccache found. Please be aware that recompiling all source files may be required. You can download and install ccache from: https://github.com/ccache/ccache/blob/master/doc/INSTALL.md
|
||||
warnings.warn(warning_message)
|
||||
Running verify PaddlePaddle program ...
|
||||
I0710 06:19:32.810492 2651 pir_interpreter.cc:1524] New Executor is Running ...
|
||||
W0710 06:19:32.813128 2651 gpu_resources.cc:114] Please NOTE: device: 0, GPU Compute Capability: 7.5, Driver API Version: 12.0, Runtime API Version: 11.7
|
||||
I0710 06:19:35.382279 2651 pir_interpreter.cc:1547] pir interpreter is running by multi-thread mode ...
|
||||
PaddlePaddle works well on 1 GPU.
|
||||
PaddlePaddle is installed successfully! Let's start deep learning with PaddlePaddle now.
|
||||
```
|
||||
|
||||
## 1.2 下载paddleocr
|
||||
|
||||
下载网站:https://github.com/PaddlePaddle/PaddleOCR/releases
|
||||
|
||||
当前使用的版本是 3.1.0
|
||||
|
||||
下载后解压
|
||||
|
||||
```bash
|
||||
unzip PaddleOCR-3.1.0.zip
|
||||
```
|
||||
|
||||
安装依赖
|
||||
|
||||
```bash
|
||||
cd PaddleOCR-3.1.0
|
||||
|
||||
pip install -r requirements.txt --user
|
||||
```
|
||||
|
||||
测试是否能正常运行:
|
||||
|
||||
```bash
|
||||
python tools/infer/predict_system.py --image_dir="/workspace/img/" --use_angle_cls=True --use_space_char=True
|
||||
```
|
||||
|
||||
输出以下内容即成功:
|
||||
```
|
||||
ppocr INFO: not find det model file path None
|
||||
```
|
||||
|
||||
|
||||
|
||||
# 2 准备数据集
|
||||
|
||||
## 2.1 标注工具
|
||||
|
||||
### 2.1.1 PPOcrLabel
|
||||
|
||||
> 存在问题:EXE 安装包运行会报错。但是该工具在本地运行标注的话还是比较推荐的。
|
||||
|
||||
下载地址:
|
||||
|
||||
- 专门为 PPOCR 制作的标注工具
|
||||
|
||||
|
||||
|
||||
### 2.1.2 X-AnyLabeling
|
||||
|
||||
下载地址:
|
||||
|
||||
- 支持多种导出格式,其中就支持 PPOCR 的格式
|
||||
|
||||
|
||||
|
||||
## 2.2 数据集结构
|
||||
|
||||
示例:
|
||||
|
||||
```
|
||||
conno/1b4e2845-e9ba-4233-9268-bf07801ace0e.jpg [{"transcription": "RKSU5020243", "points": [[233, 317], [299, 317], [258, 833], [181, 839]], "difficult": false}]
|
||||
conno/6ffd244b-1d27-4084-998b-e4d7ac076c5f.jpg [{"transcription": "ZGXU6173701", "points": [[717, 448], [781, 419], [835, 980], [751, 996]], "difficult": false}]
|
||||
conno/0ba730a8-052b-4662-88fa-bfd3c7dbd118.jpg [{"transcription": "WHLU5706937", "points": [[565, 567], [915, 485], [915, 551], [578, 635]], "difficult": false}]
|
||||
conno/8f50bf55-f825-43ac-87a5-f744aa3c2099.jpg [{"transcription": "EISU9420010", "points": [[295, 744], [624, 747], [618, 813], [299, 806]], "difficult": false}]
|
||||
conno/33e22c52-64b6-4715-87d9-d3a7823b97f7.jpg [{"transcription": "SSKU1302201", "points": [[660, 676], [960, 671], [966, 724], [662, 737]], "difficult": false}]
|
||||
conno/34a24249-7670-4be2-981f-19c502ee7da2.jpg [{"transcription": "TKRU4507940", "points": [[660, 395], [724, 395], [717, 882], [619, 902]], "difficult": false}]
|
||||
conno/67ead2d0-89c0-455c-aef0-49a76a3492aa.jpg [{"transcription": "待识别", "points": [[585, 415], [589, 415], [593, 501], [917, 341], [893, 263]], "difficult": false}]
|
||||
conno/78c58cfa-ff0f-4890-9fd9-07a0b639b9ca.jpg [{"transcription": "LYGU3568255", "points": [[553, 393], [587, 491], [972, 334], [983, 245]], "difficult": false}]
|
||||
conno/481aee74-f9ce-4145-a8c7-f4c1f45fcc75.jpg [{"transcription": "RKSU4005584", "points": [[56, 298], [19, 935], [101, 937], [115, 280]], "difficult": false}]
|
||||
conno/630d6e72-f99d-4922-8886-ea14f9e1a9bd.jpg [{"transcription": "FCIU2682384", "points": [[562, 737], [572, 803], [867, 712], [858, 655]], "difficult": false}]
|
||||
conno/9751b358-0b48-4006-8a73-89e816d37b67.jpg [{"transcription": "CNIU2452605", "points": [[608, 801], [606, 867], [908, 837], [906, 773]], "difficult": false}]
|
||||
```
|
||||
|
||||
# 3 准备预训练模型
|
||||
|
||||
> 如果已经有预训练模型的话,可以忽略这一步。
|
||||
|
||||
下载地址:https://github.com/PaddlePaddle/PaddleOCR/blob/release/3.1/docs/version3.x/model_list.md
|
||||
|
||||
如果报 404 的话,根据 版本 + 路径 进行查找即可。
|
||||
|
||||
## 3.1 文本检测训练模型
|
||||
|
||||
PP-OCRv5_mobile_det
|
||||
|
||||

|
||||
|
||||
## 3.2 文本识别训练模型
|
||||
|
||||
PP-OCRv5_mobile_rec
|
||||
|
||||

|
||||
|
||||
# 4 数据整理
|
||||
|
||||
## 4.1 检测模型所需数据准备
|
||||
|
||||
|
||||
|
||||
# 报错处理
|
||||
|
||||
## ImportError: libGL.so.1: cannot open shared object file: No such file or directory
|
||||
|
||||
### 问题原因
|
||||
|
||||
- 缺少 `libGL.so.1` 库
|
||||
|
||||
### 解决方案
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install libgl1-mesa-glx
|
||||
```
|
||||
|
||||
|
||||
|
||||
File renamed without changes.
File renamed without changes.
@@ -1,189 +0,0 @@
|
||||
# 通用错误
|
||||
|
||||
## Microsoft Visual C++ 14.0 or greater is required.
|
||||
|
||||
### 1. 下载Microsoft C++ Build Tools
|
||||
打开网址:[Microsoft C++ Build Tools](https://visualstudio.microsoft.com/zh-hans/visual-cpp-build-tools/)
|
||||
|
||||
点击下载【下载生成工具】,并打开。
|
||||
|
||||

|
||||
|
||||
接着在Workloads中,点击选择【C++ build tools】
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
并选择单个组件的C++工具开始下载。
|
||||
|
||||
### 2. 重启
|
||||
显示下载完成后,重启机器即可。
|
||||
|
||||
# [xclabel](https://gitee.com/Vanishi/xclabel)
|
||||
|
||||
## 环境
|
||||
|
||||
- python:3.10
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
git clone https://gitee.com/Vanishi/xclabel.git
|
||||
```
|
||||
|
||||
创建虚拟环境
|
||||
|
||||
```bash
|
||||
conda create -n xclabel python=3.10
|
||||
|
||||
conda activate xclabel
|
||||
|
||||
//更新pip
|
||||
python -m pip install --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
|
||||
//安装requirements
|
||||
python -m pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
```
|
||||
|
||||
## 运行
|
||||
|
||||
- 环境安装完成后,启动服务: python manage.py runserver 0.0.0.0:9924
|
||||
- 访问服务:在浏览器输入 [http://127.0.0.1:9924](https://gitee.com/link?target=http%3A%2F%2F127.0.0.1%3A9924) 就可以开始了,默认账号 admin admin888
|
||||
|
||||
|
||||
|
||||
## 报错
|
||||
|
||||
### FileNotFoundError: [WinError 3] 系统找不到指定的路径。: 'E:\\'
|
||||
|
||||
修改 config.json 配置路径即可
|
||||
|
||||
```json
|
||||
{
|
||||
"host": "127.0.0.1",
|
||||
"port": 9924,
|
||||
"ffmpeg": "ffmpeg",
|
||||
"storageDir": "D:\\project\\bxc\\gitee\\xclabel\\static\\storage",
|
||||
"yolo8": {
|
||||
"install_dir": "D:\\project\\ai\\yolov8",
|
||||
"venv": "venv\\Scripts\\activate.bat",
|
||||
"name": "yolo",
|
||||
"model": "yolov8n.pt"
|
||||
},
|
||||
"yolo11": {
|
||||
"install_dir": "D:\\project\\ai\\yolov11",
|
||||
"venv": "venv\\Scripts\\activate.bat",
|
||||
"name": "yolo",
|
||||
"model": "yolo11n.pt"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
# [PPOCRLabel](https://github.com/PFCCLab/PPOCRLabel)
|
||||
|
||||
## 环境
|
||||
|
||||
- python:3.9
|
||||
- paddlepadle:3.0.0
|
||||
- ppocrlabel:3.1.1
|
||||
|
||||
## 安装
|
||||
|
||||
创建虚拟环境
|
||||
|
||||
```bash
|
||||
conda create -n ppocrlabel python=3.9
|
||||
conda activate ppocrlabel
|
||||
```
|
||||
|
||||
安装PaddlePaddle
|
||||
|
||||
```bash
|
||||
pip3 install --upgrade pip
|
||||
|
||||
python -m pip install paddlepaddle-gpu==3.0.0 -i https://www.paddlepaddle.org.cn/packages/stable/cu126/
|
||||
```
|
||||
|
||||
下载 [PPOCRLabel](https://github.com/PFCCLab/PPOCRLabel)
|
||||
|
||||
```bash
|
||||
git clone https://github.com/PFCCLab/PPOCRLabel.git
|
||||
```
|
||||
|
||||
安装相关依赖
|
||||
|
||||
```bash
|
||||
pip install pyproject.toml
|
||||
|
||||
|
||||
pip install openpyxl
|
||||
pip install opencv-python
|
||||
pip install PyQt5
|
||||
pip install pandas
|
||||
pip install paddleocr
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 启动
|
||||
|
||||
```bash
|
||||
python PPOCRLabel.py --lang ch
|
||||
```
|
||||
|
||||
出现以下页面即代表启动成功
|
||||
|
||||

|
||||
|
||||
## 打包 exe
|
||||
|
||||
```bash
|
||||
cd ./PPOCRLabel
|
||||
# 安装pyinstaller
|
||||
pip install pyinstaller
|
||||
|
||||
# 重新生成资源
|
||||
pyrcc5 -o libs/resources.py resources.qrc
|
||||
|
||||
# 打包可执行程序
|
||||
pyinstaller -c PPOCRLabel.py --add-data "D:\\devtool/anaconda3\\envs\\ppocrlabel\\Lib\\site-packages\\paddlex;./paddlex" --collect-all paddleocr --collect-all pyclipper --collect-all imghdr --collect-all skimage --collect-all imgaug --collect-all scipy.io --collect-all lmdb --collect-all paddle --hidden-import=pyqt5 -p ./libs -p ./ -p ./data -p ./resources -F
|
||||
|
||||
pyinstaller -F -w --clean --add-data "D:/devtool/anaconda3/envs/ppocrlabel/Lib/site-packages/paddlex;./paddlex" --collect-all paddleocr --collect-all pyclipper --collect-all imghdr --collect-all skimage --collect-all imgaug --collect-all scipy.io --collect-all lmdb --collect-all paddle --collect-submodules paddleocr --collect-submodules paddlex --collect-submodules paddlex.inference.pipelines --collect-submodules paddlex.utils --collect-submodules paddlex.visualize --collect-submodules paddlex.cv.models --hidden-import=pyqt5 --hidden-import=shapely --hidden-import=visualdl --hidden-import=skimage.metrics -p ./libs -p ./ -p ./data -p ./resources PPOCRLabel.py
|
||||
|
||||
|
||||
|
||||
# 运行dist中的可执行程序,以windows为例
|
||||
PPOCRLabel.exe --lang ch
|
||||
```
|
||||
|
||||
## 报错
|
||||
|
||||
### DLL load failed while importing aggregations
|
||||
|
||||
**conda虚拟环境下**报这个错误,解决方案
|
||||
|
||||
```bash
|
||||
conda install pandas
|
||||
```
|
||||
|
||||
验证
|
||||
|
||||
```python
|
||||
import pandas as pd
|
||||
print(pd.__version__)
|
||||
df = pd.DataFrame({"a": [1, 2], "b": [3, 4]})
|
||||
print(df)
|
||||
```
|
||||
|
||||
输出下面结果,代表成功
|
||||
|
||||
```
|
||||
2.3.0
|
||||
a b
|
||||
0 1 3
|
||||
1 2 4
|
||||
```
|
||||
|
||||
Reference in new issue
Block a user