diff --git a/code/email/Email-Springboot/src/main/java/com/email/Test.java b/code/email/Email-Springboot/src/main/java/com/email/Test.java index 28c9e742..45ad5587 100644 --- a/code/email/Email-Springboot/src/main/java/com/email/Test.java +++ b/code/email/Email-Springboot/src/main/java/com/email/Test.java @@ -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 -> { + + } + ); + } } diff --git a/code/email/Email-Springboot/src/main/java/com/email/client/EmailImapClient.java b/code/email/Email-Springboot/src/main/java/com/email/client/EmailImapClient.java index 74a58a39..e325a22d 100644 --- a/code/email/Email-Springboot/src/main/java/com/email/client/EmailImapClient.java +++ b/code/email/Email-Springboot/src/main/java/com/email/client/EmailImapClient.java @@ -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"); diff --git a/code/email/Email-Springboot/src/main/java/com/email/client/EmailImapClient2.java b/code/email/Email-Springboot/src/main/java/com/email/client/EmailImapClient2.java new file mode 100644 index 00000000..4655b1a5 --- /dev/null +++ b/code/email/Email-Springboot/src/main/java/com/email/client/EmailImapClient2.java @@ -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 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); + } +} diff --git a/code/email/Email-Springboot/src/main/java/com/email/client/ImapUtf7.java b/code/email/Email-Springboot/src/main/java/com/email/client/ImapUtf7.java deleted file mode 100644 index a7b942c3..00000000 --- a/code/email/Email-Springboot/src/main/java/com/email/client/ImapUtf7.java +++ /dev/null @@ -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(); - } -} diff --git a/code/email/Email-Springboot/src/main/java/com/email/core/fetch/EmailFetcher.java b/code/email/Email-Springboot/src/main/java/com/email/core/fetch/EmailFetcher.java new file mode 100644 index 00000000..e2a48016 --- /dev/null +++ b/code/email/Email-Springboot/src/main/java/com/email/core/fetch/EmailFetcher.java @@ -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 emailFetchProgressConsumer, + Consumer emailFolderConsumer, + Consumer emailFetchDataConsumer); +} diff --git a/code/email/Email-Springboot/src/main/java/com/email/core/fetch/ImapCommandEmailFetcher.java b/code/email/Email-Springboot/src/main/java/com/email/core/fetch/ImapCommandEmailFetcher.java new file mode 100644 index 00000000..446826e1 --- /dev/null +++ b/code/email/Email-Springboot/src/main/java/com/email/core/fetch/ImapCommandEmailFetcher.java @@ -0,0 +1,4 @@ +package com.email.core.fetch; + +public class ImapCommandEmailFetcher { +} diff --git a/code/email/Email-Springboot/src/main/java/com/email/core/fetch/ImapJavaMailEmailFetcher.java b/code/email/Email-Springboot/src/main/java/com/email/core/fetch/ImapJavaMailEmailFetcher.java new file mode 100644 index 00000000..c0dcd3bd --- /dev/null +++ b/code/email/Email-Springboot/src/main/java/com/email/core/fetch/ImapJavaMailEmailFetcher.java @@ -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 progressConsumer, Consumer folderConsumer, Consumer fetchDataConsumer) { + Store store = null; + try { + store = connect(userAccount); // connect 内部已处理异常 + + List 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 listAllFolders(Folder folder) throws MessagingException { + List 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 progressConsumer, + Consumer folderConsumer, + Consumer 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); + } + } + +} diff --git a/code/email/Email-Springboot/src/main/java/com/email/core/fetch/model/EmailFetchData.java b/code/email/Email-Springboot/src/main/java/com/email/core/fetch/model/EmailFetchData.java new file mode 100644 index 00000000..aee7b069 --- /dev/null +++ b/code/email/Email-Springboot/src/main/java/com/email/core/fetch/model/EmailFetchData.java @@ -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 emailAddressList; + private List emailFileList; +} diff --git a/code/email/Email-Springboot/src/main/java/com/email/core/fetch/model/EmailFetchProgress.java b/code/email/Email-Springboot/src/main/java/com/email/core/fetch/model/EmailFetchProgress.java new file mode 100644 index 00000000..539b658c --- /dev/null +++ b/code/email/Email-Springboot/src/main/java/com/email/core/fetch/model/EmailFetchProgress.java @@ -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; // 总数 +} diff --git a/code/email/Email-Springboot/src/main/java/com/email/core/send/EmailSender.java b/code/email/Email-Springboot/src/main/java/com/email/core/send/EmailSender.java new file mode 100644 index 00000000..cee33f5a --- /dev/null +++ b/code/email/Email-Springboot/src/main/java/com/email/core/send/EmailSender.java @@ -0,0 +1,4 @@ +package com.email.core.send; + +public interface EmailSender { +} diff --git a/code/email/Email-Springboot/src/main/java/com/email/core/send/SmtpCommandEmailSender.java b/code/email/Email-Springboot/src/main/java/com/email/core/send/SmtpCommandEmailSender.java new file mode 100644 index 00000000..1265a3d1 --- /dev/null +++ b/code/email/Email-Springboot/src/main/java/com/email/core/send/SmtpCommandEmailSender.java @@ -0,0 +1,4 @@ +package com.email.core.send; + +public class SmtpCommandEmailSender { +} diff --git a/code/email/Email-Springboot/src/main/java/com/email/core/send/SmtpJavaMailEmailSender.java b/code/email/Email-Springboot/src/main/java/com/email/core/send/SmtpJavaMailEmailSender.java new file mode 100644 index 00000000..1211ca15 --- /dev/null +++ b/code/email/Email-Springboot/src/main/java/com/email/core/send/SmtpJavaMailEmailSender.java @@ -0,0 +1,4 @@ +package com.email.core.send; + +public class SmtpJavaMailEmailSender { +} diff --git a/code/email/Email-Springboot/src/main/java/com/email/domain/dto/EmailSentDTO.java b/code/email/Email-Springboot/src/main/java/com/email/domain/dto/EmailSentDTO.java index b47c975c..d577f572 100644 --- a/code/email/Email-Springboot/src/main/java/com/email/domain/dto/EmailSentDTO.java +++ b/code/email/Email-Springboot/src/main/java/com/email/domain/dto/EmailSentDTO.java @@ -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; diff --git a/code/email/Email-Springboot/src/main/java/com/email/domain/entity/EmailFile.java b/code/email/Email-Springboot/src/main/java/com/email/domain/entity/EmailFile.java index 01d16368..4734b300 100644 --- a/code/email/Email-Springboot/src/main/java/com/email/domain/entity/EmailFile.java +++ b/code/email/Email-Springboot/src/main/java/com/email/domain/entity/EmailFile.java @@ -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; } - diff --git a/code/email/Email-Springboot/src/main/java/com/email/enums/ResponseEnum.java b/code/email/Email-Springboot/src/main/java/com/email/enums/ResponseEnum.java index 34d60e43..b96fdf42 100644 --- a/code/email/Email-Springboot/src/main/java/com/email/enums/ResponseEnum.java +++ b/code/email/Email-Springboot/src/main/java/com/email/enums/ResponseEnum.java @@ -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; //相应信息 diff --git a/notes/后端开发/paddlepaddle/paddleocr.md b/notes/后端开发/paddlepaddle/paddleocr.md deleted file mode 100644 index e69de29b..00000000 diff --git a/notes/后端开发/python/assets/集装箱号识别/image-20250630093753262.png b/notes/后端开发/python/assets/集装箱号识别/image-20250630093753262.png deleted file mode 100644 index 06e029a0..00000000 Binary files a/notes/后端开发/python/assets/集装箱号识别/image-20250630093753262.png and /dev/null differ diff --git a/notes/后端开发/python/assets/集装箱号识别/image-20250630141231138.png b/notes/后端开发/python/assets/集装箱号识别/image-20250630141231138.png deleted file mode 100644 index c830e1d5..00000000 Binary files a/notes/后端开发/python/assets/集装箱号识别/image-20250630141231138.png and /dev/null differ diff --git a/notes/后端开发/python/集装箱号识别.md b/notes/后端开发/python/集装箱号识别.md deleted file mode 100644 index 0f23e502..00000000 --- a/notes/后端开发/python/集装箱号识别.md +++ /dev/null @@ -1,663 +0,0 @@ -# 识别结果 - -参数基本采用默认参数,都训练 **10轮** 。 - - - - - -## PP-OCRv5_server (极好) - -识别效果:**极好** ,基本都是别出来了,并且正确。 - -![image-20250630141231138](./assets/%E9%9B%86%E8%A3%85%E7%AE%B1%E5%8F%B7%E8%AF%86%E5%88%AB/image-20250630141231138.png) - -### 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 -``` - diff --git a/notes/后端开发/深度学习/paddlepaddle/assets/paddleocr/image-20250710162227162.png b/notes/后端开发/深度学习/paddlepaddle/assets/paddleocr/image-20250710162227162.png new file mode 100644 index 00000000..0de6186a Binary files /dev/null and b/notes/后端开发/深度学习/paddlepaddle/assets/paddleocr/image-20250710162227162.png differ diff --git a/notes/后端开发/深度学习/paddlepaddle/assets/paddleocr/image-20250710162314463.png b/notes/后端开发/深度学习/paddlepaddle/assets/paddleocr/image-20250710162314463.png new file mode 100644 index 00000000..8cacebbf Binary files /dev/null and b/notes/后端开发/深度学习/paddlepaddle/assets/paddleocr/image-20250710162314463.png differ diff --git a/notes/后端开发/深度学习/paddlepaddle/assets/paddleocr/image-20250710162351772.png b/notes/后端开发/深度学习/paddlepaddle/assets/paddleocr/image-20250710162351772.png new file mode 100644 index 00000000..a71feaeb Binary files /dev/null and b/notes/后端开发/深度学习/paddlepaddle/assets/paddleocr/image-20250710162351772.png differ diff --git a/notes/后端开发/paddlepaddle/paddlenlp.md b/notes/后端开发/深度学习/paddlepaddle/paddlenlp.md similarity index 100% rename from notes/后端开发/paddlepaddle/paddlenlp.md rename to notes/后端开发/深度学习/paddlepaddle/paddlenlp.md diff --git a/notes/后端开发/深度学习/paddlepaddle/paddleocr.md b/notes/后端开发/深度学习/paddlepaddle/paddleocr.md new file mode 100644 index 00000000..0ca45ee1 --- /dev/null +++ b/notes/后端开发/深度学习/paddlepaddle/paddleocr.md @@ -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 + +![image-20250710162314463](./assets/paddleocr/image-20250710162314463.png) + +## 3.2 文本识别训练模型 + +PP-OCRv5_mobile_rec + +![image-20250710162351772](./assets/paddleocr/image-20250710162351772.png) + +# 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 +``` + + + diff --git a/notes/后端开发/paddlepaddle/paddlex.md b/notes/后端开发/深度学习/paddlepaddle/paddlex.md similarity index 100% rename from notes/后端开发/paddlepaddle/paddlex.md rename to notes/后端开发/深度学习/paddlepaddle/paddlex.md diff --git a/notes/后端开发/paddlepaddle/ppocrlabel.md b/notes/后端开发/深度学习/paddlepaddle/ppocrlabel.md similarity index 100% rename from notes/后端开发/paddlepaddle/ppocrlabel.md rename to notes/后端开发/深度学习/paddlepaddle/ppocrlabel.md diff --git a/notes/软件工具/标注工具.md b/notes/软件工具/标注工具.md deleted file mode 100644 index d0b1f2b0..00000000 --- a/notes/软件工具/标注工具.md +++ /dev/null @@ -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/) - -点击下载【下载生成工具】,并打开。 - -![在这里插入图片描述](./assets/%E6%A0%87%E6%B3%A8%E5%B7%A5%E5%85%B7/ccf75e7381f40c3d3c0438abf4b4bc83.png) - -接着在Workloads中,点击选择【C++ build tools】 - -![在这里插入图片描述](./assets/%E6%A0%87%E6%B3%A8%E5%B7%A5%E5%85%B7/18e76d4498f8da5b0113fe89da2a3809.png) - -![在这里插入图片描述](./assets/%E6%A0%87%E6%B3%A8%E5%B7%A5%E5%85%B7/0cea5d0928af789071db2756e1651a25.png) - -并选择单个组件的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 -``` - -出现以下页面即代表启动成功 - -![image-20250702110516138](./assets/%E6%A0%87%E6%B3%A8%E5%B7%A5%E5%85%B7/image-20250702110516138.png) - -## 打包 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 -``` -