Spaces:
Sleeping
Sleeping
HaochenGong commited on
Commit ·
b3e6fcf
1
Parent(s): 5700698
- .idea/workspace.xml +43 -26
- 1.txt +54 -52
- CDM/detect_classify/classification.py +238 -85
- CDM/detect_compo/lib_ip/ip_draw.py +3 -0
- CDM/detect_merge/Element.py +570 -10
- CDM/detect_merge/merge.py +40 -1
- CDM/run_single.py +59 -54
- SEM/get_text.py +66 -1
- SEM/run_single_sem.py +5 -5
- SEM/txt/1/children.txt +1 -0
- SEM/txt/1/data_types.txt +62 -0
- SEM/txt/1/protect_information.txt +2 -0
- SEM/txt/1/share_information.txt +7 -0
- SEM/txt/1/thrid_party.txt +3 -0
- SEM/txt/1/update.txt +1 -0
- SEM/txt/1/user_right.txt +7 -0
- app.py +151 -154
- logs/app.log +0 -2
.idea/workspace.xml
CHANGED
|
@@ -4,14 +4,25 @@
|
|
| 4 |
<option name="autoReloadType" value="SELECTIVE" />
|
| 5 |
</component>
|
| 6 |
<component name="ChangeListManager">
|
| 7 |
-
<list default="true" id="5e4481c0-7ba2-42e4-bbe6-4c36a0d36baa" name="Changes" comment="
|
| 8 |
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
| 9 |
<change beforePath="$PROJECT_DIR$/1.txt" beforeDir="false" afterPath="$PROJECT_DIR$/1.txt" afterDir="false" />
|
|
|
|
| 10 |
<change beforePath="$PROJECT_DIR$/CDM/detect_compo/lib_ip/ip_draw.py" beforeDir="false" afterPath="$PROJECT_DIR$/CDM/detect_compo/lib_ip/ip_draw.py" afterDir="false" />
|
|
|
|
|
|
|
| 11 |
<change beforePath="$PROJECT_DIR$/CDM/run_single.py" beforeDir="false" afterPath="$PROJECT_DIR$/CDM/run_single.py" afterDir="false" />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
<change beforePath="$PROJECT_DIR$/app.py" beforeDir="false" afterPath="$PROJECT_DIR$/app.py" afterDir="false" />
|
| 13 |
<change beforePath="$PROJECT_DIR$/logs/app.log" beforeDir="false" afterPath="$PROJECT_DIR$/logs/app.log" afterDir="false" />
|
| 14 |
-
<change beforePath="$PROJECT_DIR$/logs/app.log.2024-08-20" beforeDir="false" />
|
| 15 |
</list>
|
| 16 |
<option name="SHOW_DIALOG" value="false" />
|
| 17 |
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
|
@@ -40,22 +51,27 @@
|
|
| 40 |
<option name="hideEmptyMiddlePackages" value="true" />
|
| 41 |
<option name="showLibraryContents" value="true" />
|
| 42 |
</component>
|
| 43 |
-
<component name="PropertiesComponent">{
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
|
|
|
| 55 |
}
|
| 56 |
-
}</component>
|
| 57 |
<component name="RecentsManager">
|
|
|
|
|
|
|
|
|
|
| 58 |
<key name="MoveFile.RECENT_KEYS">
|
|
|
|
| 59 |
<recent name="$PROJECT_DIR$" />
|
| 60 |
<recent name="$PROJECT_DIR$/web_design" />
|
| 61 |
<recent name="$PROJECT_DIR$/google_drive_credentials" />
|
|
@@ -102,14 +118,7 @@
|
|
| 102 |
<workItem from="1723386970626" duration="451000" />
|
| 103 |
<workItem from="1723387453009" duration="27328000" />
|
| 104 |
<workItem from="1723978405562" duration="51637000" />
|
| 105 |
-
<workItem from="1725925225487" duration="
|
| 106 |
-
</task>
|
| 107 |
-
<task id="LOCAL-00006" summary="dubug">
|
| 108 |
-
<created>1723390353091</created>
|
| 109 |
-
<option name="number" value="00006" />
|
| 110 |
-
<option name="presentableId" value="LOCAL-00006" />
|
| 111 |
-
<option name="project" value="LOCAL" />
|
| 112 |
-
<updated>1723390353091</updated>
|
| 113 |
</task>
|
| 114 |
<task id="LOCAL-00007" summary="debug">
|
| 115 |
<created>1723390589691</created>
|
|
@@ -447,7 +456,14 @@
|
|
| 447 |
<option name="project" value="LOCAL" />
|
| 448 |
<updated>1724164812860</updated>
|
| 449 |
</task>
|
| 450 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 451 |
<servers />
|
| 452 |
</component>
|
| 453 |
<component name="TypeScriptGeneratedFilesManager">
|
|
@@ -470,9 +486,10 @@
|
|
| 470 |
<MESSAGE value="js" />
|
| 471 |
<MESSAGE value="test" />
|
| 472 |
<MESSAGE value="done!!!" />
|
| 473 |
-
<
|
|
|
|
| 474 |
</component>
|
| 475 |
<component name="com.intellij.coverage.CoverageDataManagerImpl">
|
| 476 |
-
<SUITE FILE_PATH="coverage/Cpp4App_test$app.coverage" NAME="app Coverage Results" MODIFIED="
|
| 477 |
</component>
|
| 478 |
</project>
|
|
|
|
| 4 |
<option name="autoReloadType" value="SELECTIVE" />
|
| 5 |
</component>
|
| 6 |
<component name="ChangeListManager">
|
| 7 |
+
<list default="true" id="5e4481c0-7ba2-42e4-bbe6-4c36a0d36baa" name="Changes" comment="output img type">
|
| 8 |
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
| 9 |
<change beforePath="$PROJECT_DIR$/1.txt" beforeDir="false" afterPath="$PROJECT_DIR$/1.txt" afterDir="false" />
|
| 10 |
+
<change beforePath="$PROJECT_DIR$/CDM/detect_classify/classification.py" beforeDir="false" afterPath="$PROJECT_DIR$/CDM/detect_classify/classification.py" afterDir="false" />
|
| 11 |
<change beforePath="$PROJECT_DIR$/CDM/detect_compo/lib_ip/ip_draw.py" beforeDir="false" afterPath="$PROJECT_DIR$/CDM/detect_compo/lib_ip/ip_draw.py" afterDir="false" />
|
| 12 |
+
<change beforePath="$PROJECT_DIR$/CDM/detect_merge/Element.py" beforeDir="false" afterPath="$PROJECT_DIR$/CDM/detect_merge/Element.py" afterDir="false" />
|
| 13 |
+
<change beforePath="$PROJECT_DIR$/CDM/detect_merge/merge.py" beforeDir="false" afterPath="$PROJECT_DIR$/CDM/detect_merge/merge.py" afterDir="false" />
|
| 14 |
<change beforePath="$PROJECT_DIR$/CDM/run_single.py" beforeDir="false" afterPath="$PROJECT_DIR$/CDM/run_single.py" afterDir="false" />
|
| 15 |
+
<change beforePath="$PROJECT_DIR$/SEM/get_text.py" beforeDir="false" afterPath="$PROJECT_DIR$/SEM/get_text.py" afterDir="false" />
|
| 16 |
+
<change beforePath="$PROJECT_DIR$/SEM/run_single_sem.py" beforeDir="false" afterPath="$PROJECT_DIR$/SEM/run_single_sem.py" afterDir="false" />
|
| 17 |
+
<change beforePath="$PROJECT_DIR$/SEM/txt/1/children.txt" beforeDir="false" afterPath="$PROJECT_DIR$/SEM/txt/1/children.txt" afterDir="false" />
|
| 18 |
+
<change beforePath="$PROJECT_DIR$/SEM/txt/1/data_types.txt" beforeDir="false" afterPath="$PROJECT_DIR$/SEM/txt/1/data_types.txt" afterDir="false" />
|
| 19 |
+
<change beforePath="$PROJECT_DIR$/SEM/txt/1/protect_information.txt" beforeDir="false" afterPath="$PROJECT_DIR$/SEM/txt/1/protect_information.txt" afterDir="false" />
|
| 20 |
+
<change beforePath="$PROJECT_DIR$/SEM/txt/1/share_information.txt" beforeDir="false" afterPath="$PROJECT_DIR$/SEM/txt/1/share_information.txt" afterDir="false" />
|
| 21 |
+
<change beforePath="$PROJECT_DIR$/SEM/txt/1/thrid_party.txt" beforeDir="false" afterPath="$PROJECT_DIR$/SEM/txt/1/thrid_party.txt" afterDir="false" />
|
| 22 |
+
<change beforePath="$PROJECT_DIR$/SEM/txt/1/update.txt" beforeDir="false" afterPath="$PROJECT_DIR$/SEM/txt/1/update.txt" afterDir="false" />
|
| 23 |
+
<change beforePath="$PROJECT_DIR$/SEM/txt/1/user_right.txt" beforeDir="false" afterPath="$PROJECT_DIR$/SEM/txt/1/user_right.txt" afterDir="false" />
|
| 24 |
<change beforePath="$PROJECT_DIR$/app.py" beforeDir="false" afterPath="$PROJECT_DIR$/app.py" afterDir="false" />
|
| 25 |
<change beforePath="$PROJECT_DIR$/logs/app.log" beforeDir="false" afterPath="$PROJECT_DIR$/logs/app.log" afterDir="false" />
|
|
|
|
| 26 |
</list>
|
| 27 |
<option name="SHOW_DIALOG" value="false" />
|
| 28 |
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
|
|
|
| 51 |
<option name="hideEmptyMiddlePackages" value="true" />
|
| 52 |
<option name="showLibraryContents" value="true" />
|
| 53 |
</component>
|
| 54 |
+
<component name="PropertiesComponent"><![CDATA[{
|
| 55 |
+
"keyToString": {
|
| 56 |
+
"DefaultHtmlFileTemplate": "HTML File",
|
| 57 |
+
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
| 58 |
+
"RunOnceActivity.ShowReadmeOnStart": "true",
|
| 59 |
+
"WebServerToolWindowFactoryState": "false",
|
| 60 |
+
"last_opened_file_path": "/Users/hika/ANU/2024 s2/8800/Cpp4App_test/CDM/detect_merge",
|
| 61 |
+
"node.js.detected.package.eslint": "true",
|
| 62 |
+
"node.js.detected.package.tslint": "true",
|
| 63 |
+
"node.js.selected.package.eslint": "(autodetect)",
|
| 64 |
+
"node.js.selected.package.tslint": "(autodetect)",
|
| 65 |
+
"nodejs_package_manager_path": "npm",
|
| 66 |
+
"vue.rearranger.settings.migration": "true"
|
| 67 |
}
|
| 68 |
+
}]]></component>
|
| 69 |
<component name="RecentsManager">
|
| 70 |
+
<key name="CopyFile.RECENT_KEYS">
|
| 71 |
+
<recent name="$PROJECT_DIR$/CDM/detect_merge" />
|
| 72 |
+
</key>
|
| 73 |
<key name="MoveFile.RECENT_KEYS">
|
| 74 |
+
<recent name="$PROJECT_DIR$/CDM/detect_merge" />
|
| 75 |
<recent name="$PROJECT_DIR$" />
|
| 76 |
<recent name="$PROJECT_DIR$/web_design" />
|
| 77 |
<recent name="$PROJECT_DIR$/google_drive_credentials" />
|
|
|
|
| 118 |
<workItem from="1723386970626" duration="451000" />
|
| 119 |
<workItem from="1723387453009" duration="27328000" />
|
| 120 |
<workItem from="1723978405562" duration="51637000" />
|
| 121 |
+
<workItem from="1725925225487" duration="133865000" />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
</task>
|
| 123 |
<task id="LOCAL-00007" summary="debug">
|
| 124 |
<created>1723390589691</created>
|
|
|
|
| 456 |
<option name="project" value="LOCAL" />
|
| 457 |
<updated>1724164812860</updated>
|
| 458 |
</task>
|
| 459 |
+
<task id="LOCAL-00055" summary="output img type">
|
| 460 |
+
<created>1725928977864</created>
|
| 461 |
+
<option name="number" value="00055" />
|
| 462 |
+
<option name="presentableId" value="LOCAL-00055" />
|
| 463 |
+
<option name="project" value="LOCAL" />
|
| 464 |
+
<updated>1725928977865</updated>
|
| 465 |
+
</task>
|
| 466 |
+
<option name="localTasksCounter" value="56" />
|
| 467 |
<servers />
|
| 468 |
</component>
|
| 469 |
<component name="TypeScriptGeneratedFilesManager">
|
|
|
|
| 486 |
<MESSAGE value="js" />
|
| 487 |
<MESSAGE value="test" />
|
| 488 |
<MESSAGE value="done!!!" />
|
| 489 |
+
<MESSAGE value="output img type" />
|
| 490 |
+
<option name="LAST_COMMIT_MESSAGE" value="output img type" />
|
| 491 |
</component>
|
| 492 |
<component name="com.intellij.coverage.CoverageDataManagerImpl">
|
| 493 |
+
<SUITE FILE_PATH="coverage/Cpp4App_test$app.coverage" NAME="app Coverage Results" MODIFIED="1728910172560" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
| 494 |
</component>
|
| 495 |
</project>
|
1.txt
CHANGED
|
@@ -46,50 +46,50 @@
|
|
| 46 |
<link rel="apple-touch-icon" href="/sites/all/themes/mcdonalds/images/apple-touch-icon.png"/>
|
| 47 |
<link href="//fonts.googleapis.com/css?family=Lato:400,300,700,900,100" rel="stylesheet" type="text/css">
|
| 48 |
<style type="text/css" media="all">
|
| 49 |
-
@import url("https://mcdonalds.com.au/modules/system/system.base.css?
|
| 50 |
-
@import url("https://mcdonalds.com.au/modules/system/system.menus.css?
|
| 51 |
-
@import url("https://mcdonalds.com.au/modules/system/system.messages.css?
|
| 52 |
-
@import url("https://mcdonalds.com.au/modules/system/system.theme.css?
|
| 53 |
</style>
|
| 54 |
<style type="text/css" media="all">
|
| 55 |
-
@import url("https://mcdonalds.com.au/sites/all/modules/blazy/css/blazy.css?
|
| 56 |
-
@import url("https://mcdonalds.com.au/sites/all/modules/blazy/css/components/blazy.filter.css?
|
| 57 |
-
@import url("https://mcdonalds.com.au/sites/all/modules/blazy/css/components/blazy.ratio.css?
|
| 58 |
-
@import url("https://mcdonalds.com.au/sites/all/modules/blazy/css/components/blazy.loading.css?
|
| 59 |
</style>
|
| 60 |
<style type="text/css" media="all">
|
| 61 |
-
@import url("https://mcdonalds.com.au/sites/all/modules/date/date_api/date.css?
|
| 62 |
-
@import url("https://mcdonalds.com.au/sites/all/modules/date/date_popup/themes/datepicker.1.7.css?
|
| 63 |
-
@import url("https://mcdonalds.com.au/modules/field/theme/field.css?
|
| 64 |
-
@import url("https://mcdonalds.com.au/sites/all/modules/mcd/mcd_afl_gather_round/css/mcd_afl_gather_round.css?
|
| 65 |
-
@import url("https://mcdonalds.com.au/sites/all/modules/mcd/mcd_fathers_day/css/mcd_fathers_day.css?
|
| 66 |
-
@import url("https://mcdonalds.com.au/sites/all/modules/mcd/mcd_mcfeast/css/mcd_mcfeast.css?
|
| 67 |
-
@import url("https://mcdonalds.com.au/sites/all/modules/mcd/mcd_mothers_day/css/mcd_mothers_day.css?
|
| 68 |
-
@import url("https://mcdonalds.com.au/sites/all/modules/mcd/mcd_nuggies/css/mcd_nuggies.css?
|
| 69 |
-
@import url("https://mcdonalds.com.au/sites/all/modules/mcd/mcd_product/css/mcd-product.css?
|
| 70 |
-
@import url("https://mcdonalds.com.au/sites/all/modules/mcd/mcd_sauce_trail_form/css/mcd_sauce_trail_form.css?
|
| 71 |
-
@import url("https://mcdonalds.com.au/modules/node/node.css?
|
| 72 |
-
@import url("https://mcdonalds.com.au/modules/search/search.css?
|
| 73 |
-
@import url("https://mcdonalds.com.au/modules/user/user.css?
|
| 74 |
-
@import url("https://mcdonalds.com.au/sites/all/modules/views/css/views.css?
|
| 75 |
</style>
|
| 76 |
<style type="text/css" media="all">
|
| 77 |
-
@import url("https://mcdonalds.com.au/sites/all/modules/ctools/css/ctools.css?
|
| 78 |
-
@import url("https://mcdonalds.com.au/sites/all/modules/mcd/mcd_lite_youtube_embed/css/lite-yt-embed.css?
|
| 79 |
-
@import url("https://mcdonalds.com.au/sites/all/modules/_patched/dismiss/css/dismiss.base.css?
|
| 80 |
</style>
|
| 81 |
<style type="text/css" media="all">
|
| 82 |
-
@import url("https://mcdonalds.com.au/sites/all/themes/mcdonalds/css/bootstrap.min.css?
|
| 83 |
-
@import url("https://mcdonalds.com.au/sites/all/themes/mcdonalds/css/flexslider.css?
|
| 84 |
-
@import url("https://mcdonalds.com.au/sites/all/themes/mcdonalds/css/main.css?
|
| 85 |
-
@import url("https://mcdonalds.com.au/sites/all/themes/mcdonalds/css/main2.css?
|
| 86 |
-
@import url("https://mcdonalds.com.au/sites/all/themes/mcdonalds/css/theme.css?
|
| 87 |
-
@import url("https://mcdonalds.com.au/sites/all/themes/mcdonalds/css/hamburgers.css?
|
| 88 |
-
@import url("https://mcdonalds.com.au/sites/all/themes/mcdonalds/css/main-responsive.css?
|
| 89 |
-
@import url("https://mcdonalds.com.au/sites/all/themes/mcdonalds/css/animate.css?
|
| 90 |
</style>
|
| 91 |
<style type="text/css" media="all">
|
| 92 |
-
@import url("https://mcdonalds.com.au/sites/all/themes/mcdonalds/css/jquery.smartbanner.css?
|
| 93 |
</style>
|
| 94 |
<style type="text/css" media="all">
|
| 95 |
<!--/*--><![CDATA[/*><!--*/
|
|
@@ -99,35 +99,35 @@
|
|
| 99 |
</style>
|
| 100 |
|
| 101 |
<!--[if lte IE 8]>
|
| 102 |
-
<link type="text/css" rel="stylesheet" href="https://mcdonalds.com.au/sites/all/themes/mcdonalds/css/ie8.css?
|
| 103 |
<![endif]-->
|
| 104 |
|
| 105 |
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/themes/mcdonalds/js/jquery-3.7.0.min.js?v=3.7.0"></script>
|
| 106 |
<script type="text/javascript" src="https://mcdonalds.com.au/misc/jquery-extend-3.4.0.js?v=3.7.0"></script>
|
| 107 |
<script type="text/javascript" src="https://mcdonalds.com.au/misc/jquery-html-prefilter-3.5.0-backport.js?v=3.7.0"></script>
|
| 108 |
<script type="text/javascript" src="https://mcdonalds.com.au/misc/jquery.once.js?v=1.2"></script>
|
| 109 |
-
<script type="text/javascript" src="https://mcdonalds.com.au/misc/drupal.js?
|
| 110 |
-
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/libraries/blazy/blazy.min.js?
|
| 111 |
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/jquery_update/js/jquery_browser.js?v=0.0.1"></script>
|
| 112 |
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/blazy/js/dblazy.min.js?v=7.x-1.2"></script>
|
| 113 |
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/blazy/js/bio.min.js?v=7.x-1.2"></script>
|
| 114 |
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/blazy/js/bio.media.min.js?v=7.x-1.2"></script>
|
| 115 |
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/blazy/js/blazy.load.min.js?v=7.x-1.2"></script>
|
| 116 |
-
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/mcd/mcd_afl_gather_round/js/mcd_afl_gather_round.js?
|
| 117 |
-
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/mcd/mcd_fathers_day/js/mcd_fathers_day.js?
|
| 118 |
-
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/mcd/mcd_mcfeast/js/mcd_mcfeast.js?
|
| 119 |
-
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/mcd/mcd_mothers_day/js/mcd_mothers_day.js?
|
| 120 |
-
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/mcd/mcd_nuggies/js/mcd_nuggies.js?
|
| 121 |
-
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/mcd/mcd_sauce_trail_form/js/mcd_sauce_trail_form.js?
|
| 122 |
-
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/lazy/lazy.js?
|
| 123 |
-
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/mcd/mcd_lite_youtube_embed/js/lite-yt-embed.js?
|
| 124 |
-
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/themes/mcdonalds/js/jquery.waypoints.min.js?
|
| 125 |
-
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/themes/mcdonalds/js/anime.min.js?
|
| 126 |
-
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/themes/mcdonalds/js/jquery.viewportchecker.min.js?
|
| 127 |
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/jquery_update/js/jquery_position.js?v=0.0.1"></script>
|
| 128 |
<script type="text/javascript">
|
| 129 |
<!--//--><![CDATA[//><!--
|
| 130 |
-
jQuery.extend(Drupal.settings, {"basePath":"\/","pathPrefix":"","setHasJsCookie":0,"ajaxPageState":{"theme":"mcdonalds","theme_token":"
|
| 131 |
//--><!]]>
|
| 132 |
</script>
|
| 133 |
<!--[if lt IE 9]>
|
|
@@ -316,6 +316,8 @@ jQuery.extend(Drupal.settings, {"basePath":"\/","pathPrefix":"","setHasJsCookie"
|
|
| 316 |
<li class="last expanded"><span class="nolink" tabindex="0">Faves</span><ul class="menu"><li class="first leaf"><a href="/menu/happy-meal">Happy Meal®</a></li>
|
| 317 |
<li class="leaf"><a href="/menu/maccas-bundle-range">Bundle Range</a></li>
|
| 318 |
<li class="leaf"><a href="/the-mcsmart-meal">The McSmart™ Meal</a></li>
|
|
|
|
|
|
|
| 319 |
<li class="last leaf"><a href="https://mcdonalds.com.au/loose-change-menu">Loose Change Menu®</a></li>
|
| 320 |
</ul></li>
|
| 321 |
</ul> </div>
|
|
@@ -967,8 +969,8 @@ jQuery.extend(Drupal.settings, {"basePath":"\/","pathPrefix":"","setHasJsCookie"
|
|
| 967 |
|
| 968 |
//--><!]]>
|
| 969 |
</script>
|
| 970 |
-
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/themes/mcdonalds/js/plugins.js?
|
| 971 |
-
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/themes/mcdonalds/js/script.js?
|
| 972 |
-
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/themes/mcdonalds/js/jquery.smartbanner.js?
|
| 973 |
</body>
|
| 974 |
</html>
|
|
|
|
| 46 |
<link rel="apple-touch-icon" href="/sites/all/themes/mcdonalds/images/apple-touch-icon.png"/>
|
| 47 |
<link href="//fonts.googleapis.com/css?family=Lato:400,300,700,900,100" rel="stylesheet" type="text/css">
|
| 48 |
<style type="text/css" media="all">
|
| 49 |
+
@import url("https://mcdonalds.com.au/modules/system/system.base.css?skt6sp");
|
| 50 |
+
@import url("https://mcdonalds.com.au/modules/system/system.menus.css?skt6sp");
|
| 51 |
+
@import url("https://mcdonalds.com.au/modules/system/system.messages.css?skt6sp");
|
| 52 |
+
@import url("https://mcdonalds.com.au/modules/system/system.theme.css?skt6sp");
|
| 53 |
</style>
|
| 54 |
<style type="text/css" media="all">
|
| 55 |
+
@import url("https://mcdonalds.com.au/sites/all/modules/blazy/css/blazy.css?skt6sp");
|
| 56 |
+
@import url("https://mcdonalds.com.au/sites/all/modules/blazy/css/components/blazy.filter.css?skt6sp");
|
| 57 |
+
@import url("https://mcdonalds.com.au/sites/all/modules/blazy/css/components/blazy.ratio.css?skt6sp");
|
| 58 |
+
@import url("https://mcdonalds.com.au/sites/all/modules/blazy/css/components/blazy.loading.css?skt6sp");
|
| 59 |
</style>
|
| 60 |
<style type="text/css" media="all">
|
| 61 |
+
@import url("https://mcdonalds.com.au/sites/all/modules/date/date_api/date.css?skt6sp");
|
| 62 |
+
@import url("https://mcdonalds.com.au/sites/all/modules/date/date_popup/themes/datepicker.1.7.css?skt6sp");
|
| 63 |
+
@import url("https://mcdonalds.com.au/modules/field/theme/field.css?skt6sp");
|
| 64 |
+
@import url("https://mcdonalds.com.au/sites/all/modules/mcd/mcd_afl_gather_round/css/mcd_afl_gather_round.css?skt6sp");
|
| 65 |
+
@import url("https://mcdonalds.com.au/sites/all/modules/mcd/mcd_fathers_day/css/mcd_fathers_day.css?skt6sp");
|
| 66 |
+
@import url("https://mcdonalds.com.au/sites/all/modules/mcd/mcd_mcfeast/css/mcd_mcfeast.css?skt6sp");
|
| 67 |
+
@import url("https://mcdonalds.com.au/sites/all/modules/mcd/mcd_mothers_day/css/mcd_mothers_day.css?skt6sp");
|
| 68 |
+
@import url("https://mcdonalds.com.au/sites/all/modules/mcd/mcd_nuggies/css/mcd_nuggies.css?skt6sp");
|
| 69 |
+
@import url("https://mcdonalds.com.au/sites/all/modules/mcd/mcd_product/css/mcd-product.css?skt6sp");
|
| 70 |
+
@import url("https://mcdonalds.com.au/sites/all/modules/mcd/mcd_sauce_trail_form/css/mcd_sauce_trail_form.css?skt6sp");
|
| 71 |
+
@import url("https://mcdonalds.com.au/modules/node/node.css?skt6sp");
|
| 72 |
+
@import url("https://mcdonalds.com.au/modules/search/search.css?skt6sp");
|
| 73 |
+
@import url("https://mcdonalds.com.au/modules/user/user.css?skt6sp");
|
| 74 |
+
@import url("https://mcdonalds.com.au/sites/all/modules/views/css/views.css?skt6sp");
|
| 75 |
</style>
|
| 76 |
<style type="text/css" media="all">
|
| 77 |
+
@import url("https://mcdonalds.com.au/sites/all/modules/ctools/css/ctools.css?skt6sp");
|
| 78 |
+
@import url("https://mcdonalds.com.au/sites/all/modules/mcd/mcd_lite_youtube_embed/css/lite-yt-embed.css?skt6sp");
|
| 79 |
+
@import url("https://mcdonalds.com.au/sites/all/modules/_patched/dismiss/css/dismiss.base.css?skt6sp");
|
| 80 |
</style>
|
| 81 |
<style type="text/css" media="all">
|
| 82 |
+
@import url("https://mcdonalds.com.au/sites/all/themes/mcdonalds/css/bootstrap.min.css?skt6sp");
|
| 83 |
+
@import url("https://mcdonalds.com.au/sites/all/themes/mcdonalds/css/flexslider.css?skt6sp");
|
| 84 |
+
@import url("https://mcdonalds.com.au/sites/all/themes/mcdonalds/css/main.css?skt6sp");
|
| 85 |
+
@import url("https://mcdonalds.com.au/sites/all/themes/mcdonalds/css/main2.css?skt6sp");
|
| 86 |
+
@import url("https://mcdonalds.com.au/sites/all/themes/mcdonalds/css/theme.css?skt6sp");
|
| 87 |
+
@import url("https://mcdonalds.com.au/sites/all/themes/mcdonalds/css/hamburgers.css?skt6sp");
|
| 88 |
+
@import url("https://mcdonalds.com.au/sites/all/themes/mcdonalds/css/main-responsive.css?skt6sp");
|
| 89 |
+
@import url("https://mcdonalds.com.au/sites/all/themes/mcdonalds/css/animate.css?skt6sp");
|
| 90 |
</style>
|
| 91 |
<style type="text/css" media="all">
|
| 92 |
+
@import url("https://mcdonalds.com.au/sites/all/themes/mcdonalds/css/jquery.smartbanner.css?skt6sp");
|
| 93 |
</style>
|
| 94 |
<style type="text/css" media="all">
|
| 95 |
<!--/*--><![CDATA[/*><!--*/
|
|
|
|
| 99 |
</style>
|
| 100 |
|
| 101 |
<!--[if lte IE 8]>
|
| 102 |
+
<link type="text/css" rel="stylesheet" href="https://mcdonalds.com.au/sites/all/themes/mcdonalds/css/ie8.css?skt6sp" media="all" />
|
| 103 |
<![endif]-->
|
| 104 |
|
| 105 |
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/themes/mcdonalds/js/jquery-3.7.0.min.js?v=3.7.0"></script>
|
| 106 |
<script type="text/javascript" src="https://mcdonalds.com.au/misc/jquery-extend-3.4.0.js?v=3.7.0"></script>
|
| 107 |
<script type="text/javascript" src="https://mcdonalds.com.au/misc/jquery-html-prefilter-3.5.0-backport.js?v=3.7.0"></script>
|
| 108 |
<script type="text/javascript" src="https://mcdonalds.com.au/misc/jquery.once.js?v=1.2"></script>
|
| 109 |
+
<script type="text/javascript" src="https://mcdonalds.com.au/misc/drupal.js?skt6sp"></script>
|
| 110 |
+
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/libraries/blazy/blazy.min.js?skt6sp"></script>
|
| 111 |
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/jquery_update/js/jquery_browser.js?v=0.0.1"></script>
|
| 112 |
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/blazy/js/dblazy.min.js?v=7.x-1.2"></script>
|
| 113 |
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/blazy/js/bio.min.js?v=7.x-1.2"></script>
|
| 114 |
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/blazy/js/bio.media.min.js?v=7.x-1.2"></script>
|
| 115 |
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/blazy/js/blazy.load.min.js?v=7.x-1.2"></script>
|
| 116 |
+
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/mcd/mcd_afl_gather_round/js/mcd_afl_gather_round.js?skt6sp"></script>
|
| 117 |
+
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/mcd/mcd_fathers_day/js/mcd_fathers_day.js?skt6sp"></script>
|
| 118 |
+
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/mcd/mcd_mcfeast/js/mcd_mcfeast.js?skt6sp"></script>
|
| 119 |
+
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/mcd/mcd_mothers_day/js/mcd_mothers_day.js?skt6sp"></script>
|
| 120 |
+
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/mcd/mcd_nuggies/js/mcd_nuggies.js?skt6sp"></script>
|
| 121 |
+
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/mcd/mcd_sauce_trail_form/js/mcd_sauce_trail_form.js?skt6sp"></script>
|
| 122 |
+
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/lazy/lazy.js?skt6sp"></script>
|
| 123 |
+
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/mcd/mcd_lite_youtube_embed/js/lite-yt-embed.js?skt6sp"></script>
|
| 124 |
+
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/themes/mcdonalds/js/jquery.waypoints.min.js?skt6sp"></script>
|
| 125 |
+
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/themes/mcdonalds/js/anime.min.js?skt6sp"></script>
|
| 126 |
+
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/themes/mcdonalds/js/jquery.viewportchecker.min.js?skt6sp"></script>
|
| 127 |
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/modules/jquery_update/js/jquery_position.js?v=0.0.1"></script>
|
| 128 |
<script type="text/javascript">
|
| 129 |
<!--//--><![CDATA[//><!--
|
| 130 |
+
jQuery.extend(Drupal.settings, {"basePath":"\/","pathPrefix":"","setHasJsCookie":0,"ajaxPageState":{"theme":"mcdonalds","theme_token":"tNQ2h_NAOR1F1de6CgnHG1rTQUSN7Ibn6OkUBfYRgyM","js":{"0":1,"sites\/all\/themes\/mcdonalds\/js\/plugins.js":1,"sites\/all\/themes\/mcdonalds\/js\/script.js":1,"sites\/all\/themes\/mcdonalds\/js\/jquery.smartbanner.js":1,"sites\/all\/themes\/mcdonalds\/js\/jquery-3.7.0.min.js":1,"misc\/jquery-extend-3.4.0.js":1,"misc\/jquery-html-prefilter-3.5.0-backport.js":1,"misc\/jquery.once.js":1,"misc\/drupal.js":1,"sites\/all\/libraries\/blazy\/blazy.min.js":1,"sites\/all\/modules\/jquery_update\/js\/jquery_browser.js":1,"sites\/all\/modules\/blazy\/js\/dblazy.min.js":1,"sites\/all\/modules\/blazy\/js\/bio.min.js":1,"sites\/all\/modules\/blazy\/js\/bio.media.min.js":1,"sites\/all\/modules\/blazy\/js\/blazy.load.min.js":1,"sites\/all\/modules\/mcd\/mcd_afl_gather_round\/js\/mcd_afl_gather_round.js":1,"sites\/all\/modules\/mcd\/mcd_fathers_day\/js\/mcd_fathers_day.js":1,"sites\/all\/modules\/mcd\/mcd_mcfeast\/js\/mcd_mcfeast.js":1,"sites\/all\/modules\/mcd\/mcd_mothers_day\/js\/mcd_mothers_day.js":1,"sites\/all\/modules\/mcd\/mcd_nuggies\/js\/mcd_nuggies.js":1,"sites\/all\/modules\/mcd\/mcd_sauce_trail_form\/js\/mcd_sauce_trail_form.js":1,"sites\/all\/modules\/lazy\/lazy.js":1,"sites\/all\/modules\/mcd\/mcd_lite_youtube_embed\/js\/lite-yt-embed.js":1,"sites\/all\/themes\/mcdonalds\/js\/jquery.waypoints.min.js":1,"sites\/all\/themes\/mcdonalds\/js\/anime.min.js":1,"sites\/all\/themes\/mcdonalds\/js\/jquery.viewportchecker.min.js":1,"sites\/all\/modules\/jquery_update\/js\/jquery_position.js":1},"css":{"modules\/system\/system.base.css":1,"modules\/system\/system.menus.css":1,"modules\/system\/system.messages.css":1,"modules\/system\/system.theme.css":1,"sites\/all\/modules\/blazy\/css\/blazy.css":1,"sites\/all\/modules\/blazy\/css\/components\/blazy.filter.css":1,"sites\/all\/modules\/blazy\/css\/components\/blazy.ratio.css":1,"sites\/all\/modules\/blazy\/css\/components\/blazy.loading.css":1,"sites\/all\/modules\/date\/date_api\/date.css":1,"sites\/all\/modules\/date\/date_popup\/themes\/datepicker.1.7.css":1,"modules\/field\/theme\/field.css":1,"sites\/all\/modules\/mcd\/mcd_afl_gather_round\/css\/mcd_afl_gather_round.css":1,"sites\/all\/modules\/mcd\/mcd_fathers_day\/css\/mcd_fathers_day.css":1,"sites\/all\/modules\/mcd\/mcd_mcfeast\/css\/mcd_mcfeast.css":1,"sites\/all\/modules\/mcd\/mcd_mothers_day\/css\/mcd_mothers_day.css":1,"sites\/all\/modules\/mcd\/mcd_nuggies\/css\/mcd_nuggies.css":1,"sites\/all\/modules\/mcd\/mcd_product\/css\/mcd-product.css":1,"sites\/all\/modules\/mcd\/mcd_sauce_trail_form\/css\/mcd_sauce_trail_form.css":1,"modules\/node\/node.css":1,"modules\/search\/search.css":1,"modules\/user\/user.css":1,"sites\/all\/modules\/views\/css\/views.css":1,"sites\/all\/modules\/ctools\/css\/ctools.css":1,"sites\/all\/modules\/mcd\/mcd_lite_youtube_embed\/css\/lite-yt-embed.css":1,"sites\/all\/modules\/_patched\/dismiss\/css\/dismiss.base.css":1,"sites\/all\/themes\/mcdonalds\/css\/bootstrap.min.css":1,"sites\/all\/themes\/mcdonalds\/css\/flexslider.css":1,"sites\/all\/themes\/mcdonalds\/css\/main.css":1,"sites\/all\/themes\/mcdonalds\/css\/main2.css":1,"sites\/all\/themes\/mcdonalds\/css\/theme.css":1,"sites\/all\/themes\/mcdonalds\/css\/hamburgers.css":1,"sites\/all\/themes\/mcdonalds\/css\/main-responsive.css":1,"sites\/all\/themes\/mcdonalds\/css\/animate.css":1,"sites\/all\/themes\/mcdonalds\/css\/jquery.smartbanner.css":1,"0":1,"sites\/all\/themes\/mcdonalds\/css\/ie8.css":1}},"dismiss":{"fadeout":"2000"},"mcd":{"current_url":"https:\/\/mcdonalds.com.au\/privacy-policy","theme_url":"\/sites\/all\/themes\/mcdonalds","pane_visible_time":{"night":"18:00-23:59","other":"00:01-17:59","morning":"23:59-00:00"},"pane_visible_weather":{"cold":"\u003C25","hot":"\u003E25"}},"maccasapp_id":"other","blazy":{"loadInvisible":false,"offset":100,"saveViewportOffsetDelay":50,"validateDelay":25,"container":""},"blazyIo":{"enabled":false,"disconnect":false,"rootMargin":"0px","threshold":[0]},"lazy":{"errorClass":"b-error","loadInvisible":false,"offset":100,"saveViewportOffsetDelay":50,"selector":".b-lazy","src":"data-src","successClass":"b-loaded","validateDelay":25}});
|
| 131 |
//--><!]]>
|
| 132 |
</script>
|
| 133 |
<!--[if lt IE 9]>
|
|
|
|
| 316 |
<li class="last expanded"><span class="nolink" tabindex="0">Faves</span><ul class="menu"><li class="first leaf"><a href="/menu/happy-meal">Happy Meal®</a></li>
|
| 317 |
<li class="leaf"><a href="/menu/maccas-bundle-range">Bundle Range</a></li>
|
| 318 |
<li class="leaf"><a href="/the-mcsmart-meal">The McSmart™ Meal</a></li>
|
| 319 |
+
<li class="leaf"><a href="/menu/maccas-mega-meal">Macca's® Mega Meal</a></li>
|
| 320 |
+
<li class="leaf"><a href="/menu/grimace-meal">The Grimace Meal</a></li>
|
| 321 |
<li class="last leaf"><a href="https://mcdonalds.com.au/loose-change-menu">Loose Change Menu®</a></li>
|
| 322 |
</ul></li>
|
| 323 |
</ul> </div>
|
|
|
|
| 969 |
|
| 970 |
//--><!]]>
|
| 971 |
</script>
|
| 972 |
+
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/themes/mcdonalds/js/plugins.js?skt6sp"></script>
|
| 973 |
+
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/themes/mcdonalds/js/script.js?skt6sp"></script>
|
| 974 |
+
<script type="text/javascript" src="https://mcdonalds.com.au/sites/all/themes/mcdonalds/js/jquery.smartbanner.js?skt6sp"></script>
|
| 975 |
</body>
|
| 976 |
</html>
|
CDM/detect_classify/classification.py
CHANGED
|
@@ -34,6 +34,33 @@ keyword_list = {'Name':['name', 'first name', 'last name', 'full name', 'real na
|
|
| 34 |
'Profile':['profile', 'account'],
|
| 35 |
'Gender':['gender']}
|
| 36 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
def get_data_type(sentence, keywords, use_gpt=True):
|
| 38 |
|
| 39 |
sent_data_type = "others"
|
|
@@ -57,7 +84,7 @@ def get_data_type(sentence, keywords, use_gpt=True):
|
|
| 57 |
|
| 58 |
response = openai.ChatCompletion.create(
|
| 59 |
# engine="text-davinci-002",
|
| 60 |
-
model="gpt-
|
| 61 |
messages=[
|
| 62 |
# {"role": "system", "content": "You are a helpful assistant."},
|
| 63 |
{"role": "user", "content": prompt}
|
|
@@ -184,85 +211,153 @@ def compo_classification(input_img, output_root, segment_root, merge_json, outpu
|
|
| 184 |
|
| 185 |
classification_start_time = time.process_time()
|
| 186 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 187 |
for compo in compos:
|
|
|
|
| 188 |
|
| 189 |
-
#
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
# comp_crop = comp_crop.reshape(1, 1, 32, 32)
|
| 194 |
-
#
|
| 195 |
-
# comp_tensor = torch.tensor(comp_crop)
|
| 196 |
-
# comp_tensor = comp_tensor.permute(0, 1, 3, 2)
|
| 197 |
-
#
|
| 198 |
-
# model = get_clf_model()
|
| 199 |
-
# pred_label = model(comp_tensor)
|
| 200 |
-
#
|
| 201 |
-
# if str(np.argmax(pred_label.cpu().data.numpy(), axis=1)[0]) in label_dic.keys():
|
| 202 |
-
# compo.label = label_dic[str(np.argmax(pred_label.cpu().data.numpy(), axis=1)[0])]
|
| 203 |
-
# elements.append(compo)
|
| 204 |
-
# else:
|
| 205 |
-
# compo.label = str(np.argmax(pred_label.cpu().data.numpy(), axis=1)[0])
|
| 206 |
|
|
|
|
|
|
|
| 207 |
if clf_model == "ResNet18":
|
| 208 |
-
|
| 209 |
-
comp_grey = grey[compo.row_min:compo.row_max, compo.col_min:compo.col_max]
|
| 210 |
-
|
| 211 |
comp_crop = cv2.resize(comp_grey, (32, 32))
|
|
|
|
|
|
|
|
|
|
| 212 |
|
|
|
|
|
|
|
|
|
|
| 213 |
comp_crop = comp_crop.reshape(1, 1, 32, 32)
|
| 214 |
-
|
| 215 |
comp_tensor = torch.tensor(comp_crop)
|
| 216 |
comp_tensor = comp_tensor.permute(0, 1, 3, 2)
|
| 217 |
-
|
| 218 |
-
model = get_clf_model(clf_model)
|
| 219 |
-
pred_label = model(comp_tensor)
|
| 220 |
-
|
| 221 |
-
if str(np.argmax(pred_label.cpu().data.numpy(), axis=1)[0]) in label_dic.keys():
|
| 222 |
-
compo.label = label_dic[str(np.argmax(pred_label.cpu().data.numpy(), axis=1)[0])]
|
| 223 |
-
elements.append(compo)
|
| 224 |
-
else:
|
| 225 |
-
compo.label = str(np.argmax(pred_label.cpu().data.numpy(), axis=1)[0])
|
| 226 |
-
|
| 227 |
elif clf_model == "ViT":
|
| 228 |
-
|
| 229 |
-
comp_grey = grey[compo.row_min:compo.row_max, compo.col_min:compo.col_max]
|
| 230 |
-
|
| 231 |
-
comp_crop = cv2.resize(comp_grey, (224, 224))
|
| 232 |
-
|
| 233 |
-
# Convert the image to tensor
|
| 234 |
comp_tensor = torch.from_numpy(comp_crop)
|
| 235 |
-
|
| 236 |
-
# Reshape and repeat along the channel dimension to convert to RGB
|
| 237 |
comp_tensor = comp_tensor.view(1, 224, 224).repeat(3, 1, 1)
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
output = model(comp_tensor)
|
|
|
|
| 249 |
|
| 250 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 251 |
_, predicted = torch.max(output.logits, 1)
|
|
|
|
| 252 |
|
| 253 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 254 |
|
| 255 |
-
|
| 256 |
-
compo.label = label_dic[str(predicted.cpu().numpy()[0])]
|
| 257 |
-
elements.append(compo)
|
| 258 |
-
else:
|
| 259 |
-
compo.label = str(predicted.cpu().numpy()[0])
|
| 260 |
|
| 261 |
-
|
| 262 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 263 |
|
| 264 |
time_cost_ic = time.process_time() - classification_start_time
|
| 265 |
print("time cost for icon classification: %2.2f s" % time_cost_ic)
|
|
|
|
| 266 |
# ic_time_cost_all.append(time_cost_ic)
|
| 267 |
|
| 268 |
# --------- end classification ----------
|
|
@@ -306,34 +401,13 @@ def compo_classification(input_img, output_root, segment_root, merge_json, outpu
|
|
| 306 |
|
| 307 |
time_cost_ts = time.process_time() - text_selection_time
|
| 308 |
print("time cost for text selection: %2.2f s" % time_cost_ts)
|
| 309 |
-
# ts_time_cost_all.append(time_cost_ts)
|
| 310 |
-
|
| 311 |
-
# ---------- end -------------------------------
|
| 312 |
-
|
| 313 |
-
full_size_org, full_size_grey = pre.read_img(input_img)
|
| 314 |
-
ratio = full_size_org.shape[0]/org.shape[0]
|
| 315 |
-
|
| 316 |
-
show = False
|
| 317 |
-
wait_key = 0
|
| 318 |
-
|
| 319 |
-
reassign_ids(elements)
|
| 320 |
-
board = merge.show_elements(full_size_org, elements, ratio, show=show, win_name='elements after merging', wait_key=wait_key, line=3)
|
| 321 |
-
board_one_element = merge.show_one_element(full_size_org, elements, ratio, show=show, win_name='elements after merging', wait_key=wait_key, line=3)
|
| 322 |
-
|
| 323 |
-
classification_root = pjoin(output_root, 'classification')
|
| 324 |
|
| 325 |
-
|
| 326 |
-
name = input_img.replace('\\', '/').split('/')[-1][:-4]
|
| 327 |
-
components = merge.save_elements(pjoin(classification_root, name + '.json'), elements, full_size_org.shape, ratio)
|
| 328 |
-
cv2.imwrite(pjoin(classification_root, name + '.jpg'), board)
|
| 329 |
|
| 330 |
-
|
| 331 |
|
| 332 |
-
|
| 333 |
-
e_name = str(int(elements[i].id) + 1)
|
| 334 |
-
cv2.imwrite(pjoin(classification_root + '/GUI', name + '-' + e_name + '.jpg'), board_one_element[i])
|
| 335 |
|
| 336 |
-
print('[Classification Completed] Input: %s Output: %s' % (input_img, pjoin(classification_root, name + '.jpg')))
|
| 337 |
|
| 338 |
# ---------- matching result -----------
|
| 339 |
|
|
@@ -350,7 +424,7 @@ def compo_classification(input_img, output_root, segment_root, merge_json, outpu
|
|
| 350 |
|
| 351 |
for item in elements:
|
| 352 |
complete_path = pjoin(segment_root, app_id, 'classified_sentences', item.label + '.txt')
|
| 353 |
-
print("complete_path: ", complete_path)
|
| 354 |
|
| 355 |
if exists(complete_path):
|
| 356 |
|
|
@@ -377,4 +451,83 @@ def compo_classification(input_img, output_root, segment_root, merge_json, outpu
|
|
| 377 |
output_data = pd.concat([output_data, pd.DataFrame([{'screenshot': 's' + str(index), 'id': item.id + 1,
|
| 378 |
'label': item.label, 'index': "None",
|
| 379 |
'text': "No information!", 'sentences': "None"}])])
|
| 380 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
'Profile':['profile', 'account'],
|
| 35 |
'Gender':['gender']}
|
| 36 |
|
| 37 |
+
|
| 38 |
+
def summarize_segment(segment, label, word_limit=20):
|
| 39 |
+
openai.api_key = os.environ.get('openai_key')
|
| 40 |
+
|
| 41 |
+
# 在提示中明确要求缩略后的段落字数不超过给定的字数
|
| 42 |
+
prompt = (
|
| 43 |
+
f"Extract key information from this paragraph related to the topic '{label}' "
|
| 44 |
+
f"in no more than {word_limit} words: \"{str(segment)}\". Without using phrases like 'Key information'. "
|
| 45 |
+
|
| 46 |
+
)
|
| 47 |
+
|
| 48 |
+
response = openai.ChatCompletion.create(
|
| 49 |
+
model="gpt-4o-mini",
|
| 50 |
+
messages=[
|
| 51 |
+
{"role": "user", "content": prompt}
|
| 52 |
+
],
|
| 53 |
+
max_tokens=400, # 可以根据需要调整,确保能生成适当的长度
|
| 54 |
+
n=1,
|
| 55 |
+
stop=None,
|
| 56 |
+
temperature=0,
|
| 57 |
+
)
|
| 58 |
+
|
| 59 |
+
shortened_segment = response.choices[0].message['content'].strip()
|
| 60 |
+
|
| 61 |
+
return shortened_segment
|
| 62 |
+
|
| 63 |
+
|
| 64 |
def get_data_type(sentence, keywords, use_gpt=True):
|
| 65 |
|
| 66 |
sent_data_type = "others"
|
|
|
|
| 84 |
|
| 85 |
response = openai.ChatCompletion.create(
|
| 86 |
# engine="text-davinci-002",
|
| 87 |
+
model="gpt-4o-mini",
|
| 88 |
messages=[
|
| 89 |
# {"role": "system", "content": "You are a helpful assistant."},
|
| 90 |
{"role": "user", "content": prompt}
|
|
|
|
| 211 |
|
| 212 |
classification_start_time = time.process_time()
|
| 213 |
|
| 214 |
+
model = get_clf_model(clf_model)
|
| 215 |
+
|
| 216 |
+
# for compo in compos:
|
| 217 |
+
#
|
| 218 |
+
# # comp_grey = grey[compo.row_min:compo.row_max, compo.col_min:compo.col_max]
|
| 219 |
+
# #
|
| 220 |
+
# # comp_crop = cv2.resize(comp_grey, (32, 32))
|
| 221 |
+
# #
|
| 222 |
+
# # comp_crop = comp_crop.reshape(1, 1, 32, 32)
|
| 223 |
+
# #
|
| 224 |
+
# # comp_tensor = torch.tensor(comp_crop)
|
| 225 |
+
# # comp_tensor = comp_tensor.permute(0, 1, 3, 2)
|
| 226 |
+
# #
|
| 227 |
+
# # model = get_clf_model()
|
| 228 |
+
# # pred_label = model(comp_tensor)
|
| 229 |
+
# #
|
| 230 |
+
# # if str(np.argmax(pred_label.cpu().data.numpy(), axis=1)[0]) in label_dic.keys():
|
| 231 |
+
# # compo.label = label_dic[str(np.argmax(pred_label.cpu().data.numpy(), axis=1)[0])]
|
| 232 |
+
# # elements.append(compo)
|
| 233 |
+
# # else:
|
| 234 |
+
# # compo.label = str(np.argmax(pred_label.cpu().data.numpy(), axis=1)[0])
|
| 235 |
+
#
|
| 236 |
+
# if clf_model == "ResNet18":
|
| 237 |
+
#
|
| 238 |
+
# comp_grey = grey[compo.row_min:compo.row_max, compo.col_min:compo.col_max]
|
| 239 |
+
#
|
| 240 |
+
# comp_crop = cv2.resize(comp_grey, (32, 32))
|
| 241 |
+
#
|
| 242 |
+
# comp_crop = comp_crop.reshape(1, 1, 32, 32)
|
| 243 |
+
#
|
| 244 |
+
# comp_tensor = torch.tensor(comp_crop)
|
| 245 |
+
# comp_tensor = comp_tensor.permute(0, 1, 3, 2)
|
| 246 |
+
#
|
| 247 |
+
# # model = get_clf_model(clf_model)
|
| 248 |
+
# pred_label = model(comp_tensor)
|
| 249 |
+
#
|
| 250 |
+
# if str(np.argmax(pred_label.cpu().data.numpy(), axis=1)[0]) in label_dic.keys():
|
| 251 |
+
# compo.label = label_dic[str(np.argmax(pred_label.cpu().data.numpy(), axis=1)[0])]
|
| 252 |
+
# elements.append(compo)
|
| 253 |
+
# else:
|
| 254 |
+
# compo.label = str(np.argmax(pred_label.cpu().data.numpy(), axis=1)[0])
|
| 255 |
+
#
|
| 256 |
+
# elif clf_model == "ViT":
|
| 257 |
+
#
|
| 258 |
+
# comp_grey = grey[compo.row_min:compo.row_max, compo.col_min:compo.col_max]
|
| 259 |
+
#
|
| 260 |
+
# comp_crop = cv2.resize(comp_grey, (224, 224))
|
| 261 |
+
#
|
| 262 |
+
# # Convert the image to tensor
|
| 263 |
+
# comp_tensor = torch.from_numpy(comp_crop)
|
| 264 |
+
#
|
| 265 |
+
# # Reshape and repeat along the channel dimension to convert to RGB
|
| 266 |
+
# comp_tensor = comp_tensor.view(1, 224, 224).repeat(3, 1, 1)
|
| 267 |
+
#
|
| 268 |
+
# # comp_tensor = comp_tensor.permute(0, 2, 1)
|
| 269 |
+
#
|
| 270 |
+
# comp_tensor = comp_tensor.unsqueeze(0) # add a batch dimension
|
| 271 |
+
#
|
| 272 |
+
# # model = get_clf_model(clf_model)
|
| 273 |
+
# # pred_label = model(comp_tensor)
|
| 274 |
+
#
|
| 275 |
+
# # Forward pass through the model
|
| 276 |
+
# with torch.no_grad():
|
| 277 |
+
# output = model(comp_tensor)
|
| 278 |
+
#
|
| 279 |
+
# # Get the predicted label
|
| 280 |
+
# _, predicted = torch.max(output.logits, 1)
|
| 281 |
+
#
|
| 282 |
+
# # print("predicted_label: ", predicted.cpu().numpy())
|
| 283 |
+
#
|
| 284 |
+
# if str(predicted.cpu().numpy()[0]) in label_dic.keys():
|
| 285 |
+
# compo.label = label_dic[str(predicted.cpu().numpy()[0])]
|
| 286 |
+
# elements.append(compo)
|
| 287 |
+
# else:
|
| 288 |
+
# compo.label = str(predicted.cpu().numpy()[0])
|
| 289 |
+
#
|
| 290 |
+
# else:
|
| 291 |
+
# print("clf_model has to be ResNet18 or ViT")
|
| 292 |
+
|
| 293 |
for compo in compos:
|
| 294 |
+
compo_start_time = time.process_time()
|
| 295 |
|
| 296 |
+
# 计时预处理部分
|
| 297 |
+
preprocess_start = time.process_time()
|
| 298 |
+
comp_grey = grey[compo.row_min:compo.row_max, compo.col_min:compo.col_max]
|
| 299 |
+
preprocess_time = time.process_time() - preprocess_start
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 300 |
|
| 301 |
+
# 计时图像调整部分
|
| 302 |
+
resize_start = time.process_time()
|
| 303 |
if clf_model == "ResNet18":
|
|
|
|
|
|
|
|
|
|
| 304 |
comp_crop = cv2.resize(comp_grey, (32, 32))
|
| 305 |
+
elif clf_model == "ViT":
|
| 306 |
+
comp_crop = cv2.resize(comp_grey, (224, 224))
|
| 307 |
+
resize_time = time.process_time() - resize_start
|
| 308 |
|
| 309 |
+
# 计时张量转换部分
|
| 310 |
+
tensor_start = time.process_time()
|
| 311 |
+
if clf_model == "ResNet18":
|
| 312 |
comp_crop = comp_crop.reshape(1, 1, 32, 32)
|
|
|
|
| 313 |
comp_tensor = torch.tensor(comp_crop)
|
| 314 |
comp_tensor = comp_tensor.permute(0, 1, 3, 2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 315 |
elif clf_model == "ViT":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 316 |
comp_tensor = torch.from_numpy(comp_crop)
|
|
|
|
|
|
|
| 317 |
comp_tensor = comp_tensor.view(1, 224, 224).repeat(3, 1, 1)
|
| 318 |
+
comp_tensor = comp_tensor.unsqueeze(0)
|
| 319 |
+
tensor_time = time.process_time() - tensor_start
|
| 320 |
+
|
| 321 |
+
# 计时模型推理部分
|
| 322 |
+
inference_start = time.process_time()
|
| 323 |
+
with torch.no_grad():
|
| 324 |
+
if clf_model == "ResNet18":
|
| 325 |
+
pred_label = model(comp_tensor)
|
| 326 |
+
output = pred_label
|
| 327 |
+
elif clf_model == "ViT":
|
| 328 |
output = model(comp_tensor)
|
| 329 |
+
inference_time = time.process_time() - inference_start
|
| 330 |
|
| 331 |
+
# 计时后处理部分
|
| 332 |
+
postprocess_start = time.process_time()
|
| 333 |
+
if clf_model == "ResNet18":
|
| 334 |
+
predicted = np.argmax(output.cpu().data.numpy(), axis=1)[0]
|
| 335 |
+
elif clf_model == "ViT":
|
| 336 |
_, predicted = torch.max(output.logits, 1)
|
| 337 |
+
predicted = predicted.cpu().numpy()[0]
|
| 338 |
|
| 339 |
+
if str(predicted) in label_dic.keys():
|
| 340 |
+
compo.label = label_dic[str(predicted)]
|
| 341 |
+
elements.append(compo)
|
| 342 |
+
else:
|
| 343 |
+
compo.label = str(predicted)
|
| 344 |
+
postprocess_time = time.process_time() - postprocess_start
|
| 345 |
|
| 346 |
+
compo_total_time = time.process_time() - compo_start_time
|
|
|
|
|
|
|
|
|
|
|
|
|
| 347 |
|
| 348 |
+
# 输出每个部分的耗时
|
| 349 |
+
print("==============================================")
|
| 350 |
+
print(f"Component processing time: {compo_total_time:.4f}s")
|
| 351 |
+
print(f" Preprocessing time: {preprocess_time:.4f}s")
|
| 352 |
+
print(f" Resize time: {resize_time:.4f}s")
|
| 353 |
+
print(f" Tensor conversion time: {tensor_time:.4f}s")
|
| 354 |
+
print(f" Inference time: {inference_time:.4f}s")
|
| 355 |
+
print(f" Post-processing time: {postprocess_time:.4f}s\n")
|
| 356 |
+
print("==============================================")
|
| 357 |
|
| 358 |
time_cost_ic = time.process_time() - classification_start_time
|
| 359 |
print("time cost for icon classification: %2.2f s" % time_cost_ic)
|
| 360 |
+
print("time cost for each icon classification: %2.2f s" % (time_cost_ic/len(compos)))
|
| 361 |
# ic_time_cost_all.append(time_cost_ic)
|
| 362 |
|
| 363 |
# --------- end classification ----------
|
|
|
|
| 401 |
|
| 402 |
time_cost_ts = time.process_time() - text_selection_time
|
| 403 |
print("time cost for text selection: %2.2f s" % time_cost_ts)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 404 |
|
| 405 |
+
classification_cost = time.process_time() - classification_start_time
|
|
|
|
|
|
|
|
|
|
| 406 |
|
| 407 |
+
# ts_time_cost_all.append(time_cost_ts)
|
| 408 |
|
| 409 |
+
# ---------- end -------------------------------
|
|
|
|
|
|
|
| 410 |
|
|
|
|
| 411 |
|
| 412 |
# ---------- matching result -----------
|
| 413 |
|
|
|
|
| 424 |
|
| 425 |
for item in elements:
|
| 426 |
complete_path = pjoin(segment_root, app_id, 'classified_sentences', item.label + '.txt')
|
| 427 |
+
# print("complete_path: ", complete_path)
|
| 428 |
|
| 429 |
if exists(complete_path):
|
| 430 |
|
|
|
|
| 451 |
output_data = pd.concat([output_data, pd.DataFrame([{'screenshot': 's' + str(index), 'id': item.id + 1,
|
| 452 |
'label': item.label, 'index': "None",
|
| 453 |
'text': "No information!", 'sentences': "None"}])])
|
| 454 |
+
|
| 455 |
+
# -----------------openai缩略text---------------------------
|
| 456 |
+
|
| 457 |
+
short_text_time_start = time.process_time()
|
| 458 |
+
|
| 459 |
+
short_output_data = output_data[['label', 'text']].copy()
|
| 460 |
+
short_output_data = short_output_data.rename(columns={'text': 'segment'})
|
| 461 |
+
retries = 3
|
| 462 |
+
summarized_data = [] # List to hold summarized rows
|
| 463 |
+
for index, row in short_output_data.iterrows():
|
| 464 |
+
seg = row['segment']
|
| 465 |
+
label = row['label']
|
| 466 |
+
if seg == "No information!":
|
| 467 |
+
shortened_seg = seg
|
| 468 |
+
else:
|
| 469 |
+
for i in range(retries):
|
| 470 |
+
try:
|
| 471 |
+
shortened_seg = summarize_segment(seg, label)
|
| 472 |
+
# print(seg)
|
| 473 |
+
# print("--------------------")
|
| 474 |
+
# print(shortened_seg)
|
| 475 |
+
break
|
| 476 |
+
except openai.error.RateLimitError as e:
|
| 477 |
+
if "overloaded" in str(e):
|
| 478 |
+
print("error")
|
| 479 |
+
sleep_time = 2 * (2 ** i) + 0.1
|
| 480 |
+
# sleep_time = 3
|
| 481 |
+
time.sleep(sleep_time)
|
| 482 |
+
except Exception as e:
|
| 483 |
+
# If you wish, you can print or log the exception details here without raising it
|
| 484 |
+
print(e)
|
| 485 |
+
else:
|
| 486 |
+
# This part will be executed if the for loop doesn't hit 'break'
|
| 487 |
+
shortened_seg = seg
|
| 488 |
+
|
| 489 |
+
summarized_data.append({'label': row['label'], 'segment': shortened_seg})
|
| 490 |
+
|
| 491 |
+
short_text_time_cost = time.process_time() - short_text_time_start
|
| 492 |
+
print("缩短policy总共花费了: %2.2f s" % short_text_time_cost)
|
| 493 |
+
|
| 494 |
+
# -------------------------------------------------------
|
| 495 |
+
|
| 496 |
+
full_size_org, full_size_grey = pre.read_img(input_img)
|
| 497 |
+
ratio = full_size_org.shape[0]/org.shape[0]
|
| 498 |
+
|
| 499 |
+
show = False
|
| 500 |
+
wait_key = 0
|
| 501 |
+
|
| 502 |
+
reassign_ids(elements)
|
| 503 |
+
board = merge.show_elements(full_size_org, elements, ratio, show=show, win_name='elements after merging', wait_key=wait_key, line=3)
|
| 504 |
+
|
| 505 |
+
draw_pic_start = time.process_time()
|
| 506 |
+
|
| 507 |
+
board_one_element = merge.show_one_element_class(full_size_org, elements, ratio, show=show, win_name='elements after merging', wait_key=wait_key, line=3, summarized_data=summarized_data)
|
| 508 |
+
|
| 509 |
+
draw_pic_cost = time.process_time() - draw_pic_start
|
| 510 |
+
print("生成所有的展示图片花费: %2.2f s" % draw_pic_cost)
|
| 511 |
+
print("平均生成一张图片花费: %2.2f s" % (draw_pic_cost/len(board_one_element)))
|
| 512 |
+
|
| 513 |
+
classification_root = pjoin(output_root, 'classification')
|
| 514 |
+
|
| 515 |
+
# save all merged elements, clips and blank background
|
| 516 |
+
name = input_img.replace('\\', '/').split('/')[-1][:-4]
|
| 517 |
+
components = merge.save_elements(pjoin(classification_root, name + '.json'), elements, full_size_org.shape, ratio)
|
| 518 |
+
cv2.imwrite(pjoin(classification_root, name + '.jpg'), board)
|
| 519 |
+
|
| 520 |
+
print("一共图片张数: ", len(board_one_element))
|
| 521 |
+
|
| 522 |
+
for i in range(len(board_one_element)):
|
| 523 |
+
e_name = str(int(elements[i].id) + 1)
|
| 524 |
+
cv2.imwrite(pjoin(classification_root + '/GUI', name + '-' + e_name + '.jpg'), board_one_element[i])
|
| 525 |
+
|
| 526 |
+
print("生成图片展示总花费: %2.2f s" % (time.process_time()-short_text_time_start))
|
| 527 |
+
|
| 528 |
+
# print('[Classification Completed] Input: %s Output: %s' % (input_img, pjoin(classification_root, name + '.jpg')))
|
| 529 |
+
|
| 530 |
+
|
| 531 |
+
|
| 532 |
+
|
| 533 |
+
return time_cost_ic, time_cost_ts, output_data, board_one_element,classification_cost
|
CDM/detect_compo/lib_ip/ip_draw.py
CHANGED
|
@@ -49,6 +49,9 @@ def draw_bounding_box_class_by_category(org, components, color_map=C.COLOR, line
|
|
| 49 |
output_path = pjoin(output_root, f"{category}.jpg")
|
| 50 |
cv2.imwrite(output_path, board)
|
| 51 |
|
|
|
|
|
|
|
|
|
|
| 52 |
|
| 53 |
def draw_bounding_box_class(org, components, color_map=C.COLOR, line=2, show=False, write_path=None, name='board'):
|
| 54 |
"""
|
|
|
|
| 49 |
output_path = pjoin(output_root, f"{category}.jpg")
|
| 50 |
cv2.imwrite(output_path, board)
|
| 51 |
|
| 52 |
+
# 返回所有分类对应的图像字典
|
| 53 |
+
return boards_by_category
|
| 54 |
+
|
| 55 |
|
| 56 |
def draw_bounding_box_class(org, components, color_map=C.COLOR, line=2, show=False, write_path=None, name='board'):
|
| 57 |
"""
|
CDM/detect_merge/Element.py
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
|
|
|
|
|
| 1 |
import numpy as np
|
| 2 |
import cv2
|
|
|
|
|
|
|
| 3 |
|
| 4 |
|
| 5 |
class Element:
|
|
@@ -16,6 +20,30 @@ class Element:
|
|
| 16 |
self.children = [] # list of elements
|
| 17 |
self.label = None
|
| 18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
def init_bound(self):
|
| 20 |
self.width = self.col_max - self.col_min
|
| 21 |
self.height = self.row_max - self.row_min
|
|
@@ -25,7 +53,7 @@ class Element:
|
|
| 25 |
return self.col_min, self.row_min, self.col_max, self.row_max
|
| 26 |
|
| 27 |
def wrap_info(self):
|
| 28 |
-
info = {'id':self.id, 'class': self.category, 'height': self.height, 'width': self.width,
|
| 29 |
'position': {'column_min': self.col_min, 'row_min': self.row_min, 'column_max': self.col_max,
|
| 30 |
'row_max': self.row_max}, 'label': self.label}
|
| 31 |
if self.text_content is not None:
|
|
@@ -48,7 +76,8 @@ class Element:
|
|
| 48 |
def element_merge(self, element_b, new_element=False, new_category=None, new_id=None):
|
| 49 |
col_min_a, row_min_a, col_max_a, row_max_a = self.put_bbox()
|
| 50 |
col_min_b, row_min_b, col_max_b, row_max_b = element_b.put_bbox()
|
| 51 |
-
new_corner = (
|
|
|
|
| 52 |
if element_b.text_content is not None:
|
| 53 |
self.text_content = element_b.text_content if self.text_content is None else self.text_content + '\n' + element_b.text_content
|
| 54 |
if new_element:
|
|
@@ -95,19 +124,550 @@ class Element:
|
|
| 95 |
return 1
|
| 96 |
return 2
|
| 97 |
|
| 98 |
-
def visualize_element(self, img, color=(0, 255, 0), line=
|
| 99 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
|
|
|
|
|
|
|
| 101 |
if ratio != 1:
|
| 102 |
loc = [int(x * ratio) for x in loc]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
|
| 104 |
-
#
|
| 105 |
-
|
| 106 |
-
cv2.
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
if show:
|
| 111 |
cv2.imshow('element', img)
|
| 112 |
cv2.waitKey(0)
|
| 113 |
cv2.destroyWindow('element')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import time
|
| 2 |
+
|
| 3 |
import numpy as np
|
| 4 |
import cv2
|
| 5 |
+
import pandas as pd
|
| 6 |
+
from PIL import Image, ImageDraw, ImageFont
|
| 7 |
|
| 8 |
|
| 9 |
class Element:
|
|
|
|
| 20 |
self.children = [] # list of elements
|
| 21 |
self.label = None
|
| 22 |
|
| 23 |
+
def __str__(self):
|
| 24 |
+
return (f"Element(id={self.id}, category={self.category}, corner=({self.col_min}, {self.row_min}, "
|
| 25 |
+
f"{self.col_max}, {self.row_max}), width={self.width}, height={self.height}, area={self.area}, "
|
| 26 |
+
f"text_content={self.text_content}, label={self.label}, parent_id={self.parent_id}, "
|
| 27 |
+
f"children_count={len(self.children)})")
|
| 28 |
+
|
| 29 |
+
def __eq__(self, other):
|
| 30 |
+
if not isinstance(other, Element):
|
| 31 |
+
return False
|
| 32 |
+
return (self.id == other.id and
|
| 33 |
+
self.category == other.category and
|
| 34 |
+
self.col_min == other.col_min and
|
| 35 |
+
self.row_min == other.row_min and
|
| 36 |
+
self.col_max == other.col_max and
|
| 37 |
+
self.row_max == other.row_max and
|
| 38 |
+
self.text_content == other.text_content and
|
| 39 |
+
self.label == other.label)
|
| 40 |
+
|
| 41 |
+
def center(self):
|
| 42 |
+
# 计算中心点
|
| 43 |
+
center_x = (self.col_min + self.col_max) / 2
|
| 44 |
+
center_y = (self.row_min + self.row_max) / 2
|
| 45 |
+
return (center_x, center_y)
|
| 46 |
+
|
| 47 |
def init_bound(self):
|
| 48 |
self.width = self.col_max - self.col_min
|
| 49 |
self.height = self.row_max - self.row_min
|
|
|
|
| 53 |
return self.col_min, self.row_min, self.col_max, self.row_max
|
| 54 |
|
| 55 |
def wrap_info(self):
|
| 56 |
+
info = {'id': self.id, 'class': self.category, 'height': self.height, 'width': self.width,
|
| 57 |
'position': {'column_min': self.col_min, 'row_min': self.row_min, 'column_max': self.col_max,
|
| 58 |
'row_max': self.row_max}, 'label': self.label}
|
| 59 |
if self.text_content is not None:
|
|
|
|
| 76 |
def element_merge(self, element_b, new_element=False, new_category=None, new_id=None):
|
| 77 |
col_min_a, row_min_a, col_max_a, row_max_a = self.put_bbox()
|
| 78 |
col_min_b, row_min_b, col_max_b, row_max_b = element_b.put_bbox()
|
| 79 |
+
new_corner = (
|
| 80 |
+
min(col_min_a, col_min_b), min(row_min_a, row_min_b), max(col_max_a, col_max_b), max(row_max_a, row_max_b))
|
| 81 |
if element_b.text_content is not None:
|
| 82 |
self.text_content = element_b.text_content if self.text_content is None else self.text_content + '\n' + element_b.text_content
|
| 83 |
if new_element:
|
|
|
|
| 124 |
return 1
|
| 125 |
return 2
|
| 126 |
|
| 127 |
+
# def visualize_element(self, img, color=(0, 255, 0), line=3, show=False, ratio=1, expand_size=5, corner_radius=20):
|
| 128 |
+
# loc = self.put_bbox()
|
| 129 |
+
#
|
| 130 |
+
# if ratio != 1:
|
| 131 |
+
# loc = [int(x * ratio) for x in loc]
|
| 132 |
+
#
|
| 133 |
+
# # 调整线条粗细,根据缩放比例
|
| 134 |
+
# adjusted_thickness = int(line * ratio)
|
| 135 |
+
# if adjusted_thickness < 1:
|
| 136 |
+
# adjusted_thickness = 1 # 确保最小粗细为1
|
| 137 |
+
#
|
| 138 |
+
# # cv2.rectangle(img, loc[:2], loc[2:], color, line)
|
| 139 |
+
# # cv2.rectangle(img, (loc[0], loc[1]), (loc[2], loc[3]), color, line)
|
| 140 |
+
# # 标号
|
| 141 |
+
# # cv2.putText(img, str(int(self.id) + 1), (int(ratio*(self.col_min - 10)), int(ratio*(self.row_max + 10))),
|
| 142 |
+
# # cv2.FONT_HERSHEY_SIMPLEX, 1, color, line)
|
| 143 |
+
#
|
| 144 |
+
# # 扩展边框,在原始坐标的基础上增加 expand_size
|
| 145 |
+
# loc[0] -= expand_size # 左
|
| 146 |
+
# loc[1] -= expand_size + 2 # 上
|
| 147 |
+
# loc[2] += expand_size + 10 # 右
|
| 148 |
+
# loc[3] += expand_size + 2 # 下
|
| 149 |
+
#
|
| 150 |
+
# # 确保圆角半径不会超过矩形的宽或高的一半
|
| 151 |
+
# corner_radius = min(corner_radius, (loc[2] - loc[0]) // 2, (loc[3] - loc[1]) // 2)
|
| 152 |
+
#
|
| 153 |
+
# # 绘制圆角矩形
|
| 154 |
+
# def draw_rounded_rectangle(image, top_left, bottom_right, color, thickness, radius):
|
| 155 |
+
# x1, y1 = top_left
|
| 156 |
+
# x2, y2 = bottom_right
|
| 157 |
+
#
|
| 158 |
+
# # 计算各条边线的起点和终点
|
| 159 |
+
# points = [
|
| 160 |
+
# ((x1 + radius, y1), (x2 - radius, y1)), # 上边
|
| 161 |
+
# ((x1 + radius, y2), (x2 - radius, y2)), # 下边
|
| 162 |
+
# ((x1, y1 + radius), (x1, y2 - radius)), # 左边
|
| 163 |
+
# ((x2, y1 + radius), (x2, y2 - radius)) # 右边
|
| 164 |
+
# ]
|
| 165 |
+
#
|
| 166 |
+
# # 画四分之一圆角
|
| 167 |
+
# cv2.ellipse(image, (x1 + radius, y1 + radius), (radius, radius), 180, 0, 90, color, thickness) # 左上角
|
| 168 |
+
# cv2.ellipse(image, (x2 - radius, y1 + radius), (radius, radius), 270, 0, 90, color, thickness) # 右上角
|
| 169 |
+
# cv2.ellipse(image, (x1 + radius, y2 - radius), (radius, radius), 90, 0, 90, color, thickness) # 左下角
|
| 170 |
+
# cv2.ellipse(image, (x2 - radius, y2 - radius), (radius, radius), 0, 0, 90, color, thickness) # 右下角
|
| 171 |
+
#
|
| 172 |
+
# # 画四条直线连接四分之一圆角
|
| 173 |
+
# for point_start, point_end in points:
|
| 174 |
+
# cv2.line(image, point_start, point_end, color, thickness)
|
| 175 |
+
#
|
| 176 |
+
# # 绘制圆角矩形
|
| 177 |
+
# draw_rounded_rectangle(img, (loc[0], loc[1]), (loc[2], loc[3]), color, adjusted_thickness, corner_radius)
|
| 178 |
+
#
|
| 179 |
+
# # for child in self.children:
|
| 180 |
+
# # child.visualize_element(img, color=(255, 0, 255), line=line)
|
| 181 |
+
# if show:
|
| 182 |
+
# cv2.imshow('element', img)
|
| 183 |
+
# cv2.waitKey(0)
|
| 184 |
+
# cv2.destroyWindow('element')
|
| 185 |
|
| 186 |
+
def adjust_loc(self, ratio=1, expand_size=5):
|
| 187 |
+
loc = list(self.put_bbox())
|
| 188 |
if ratio != 1:
|
| 189 |
loc = [int(x * ratio) for x in loc]
|
| 190 |
+
# 扩展框的边界
|
| 191 |
+
loc[0] -= expand_size # 左扩展
|
| 192 |
+
loc[1] -= expand_size + 2 # 上扩展
|
| 193 |
+
loc[2] += expand_size + 10 # 右扩展
|
| 194 |
+
loc[3] += expand_size + 2 # 下扩展
|
| 195 |
+
return loc
|
| 196 |
+
|
| 197 |
+
def draw_and_expand_rounded_rectangle(self, img, loc, color=(0, 255, 0), thickness=-1, expand_size=5,
|
| 198 |
+
corner_radius=20, ):
|
| 199 |
+
"""
|
| 200 |
+
通用的绘制带扩展边框的圆角矩形的方法。
|
| 201 |
+
|
| 202 |
+
参数:
|
| 203 |
+
- img: 输入图像
|
| 204 |
+
- loc: 矩形的左上角和右下角坐标 (x1, y1, x2, y2)
|
| 205 |
+
- color: 矩形颜色
|
| 206 |
+
- line: 矩形边框线条的粗细
|
| 207 |
+
- expand_size: 扩展的边框大小
|
| 208 |
+
- corner_radius: 圆角的半径
|
| 209 |
+
- thickness: 线条粗细(-1 为填充)
|
| 210 |
+
"""
|
| 211 |
+
|
| 212 |
+
# 确保圆角半径不会超过矩形的宽或高的一半
|
| 213 |
+
corner_radius = min(corner_radius, (loc[2] - loc[0]) // 2, (loc[3] - loc[1]) // 2)
|
| 214 |
+
|
| 215 |
+
# 绘制带扩展的圆角矩形
|
| 216 |
+
x1, y1 = loc[0], loc[1]
|
| 217 |
+
x2, y2 = loc[2], loc[3]
|
| 218 |
+
|
| 219 |
+
x1 = int(x1)
|
| 220 |
+
y1 = int(y1)
|
| 221 |
+
x2 = int(x2)
|
| 222 |
+
y2 = int(y2)
|
| 223 |
+
|
| 224 |
+
# Step 1: 处理填充
|
| 225 |
+
if thickness == -1:
|
| 226 |
+
# 填充模式 - 先绘制没有圆角的矩形部分
|
| 227 |
+
cv2.rectangle(img, (x1 + corner_radius, y1), (x2 - corner_radius, y2), color, cv2.FILLED) # 上下边部分
|
| 228 |
+
cv2.rectangle(img, (x1, y1 + corner_radius), (x2, y2 - corner_radius), color, cv2.FILLED) # 左右边部分
|
| 229 |
|
| 230 |
+
# Step 2: 处理圆角
|
| 231 |
+
# 画四分之一圆角
|
| 232 |
+
cv2.ellipse(img, (x1 + corner_radius, y1 + corner_radius), (corner_radius, corner_radius), 180, 0, 90, color,
|
| 233 |
+
thickness) # 左上角
|
| 234 |
+
cv2.ellipse(img, (x2 - corner_radius, y1 + corner_radius), (corner_radius, corner_radius), 270, 0, 90, color,
|
| 235 |
+
thickness) # 右上角
|
| 236 |
+
cv2.ellipse(img, (x1 + corner_radius, y2 - corner_radius), (corner_radius, corner_radius), 90, 0, 90, color,
|
| 237 |
+
thickness) # 左下角
|
| 238 |
+
cv2.ellipse(img, (x2 - corner_radius, y2 - corner_radius), (corner_radius, corner_radius), 0, 0, 90, color,
|
| 239 |
+
thickness) # 右下角
|
| 240 |
+
|
| 241 |
+
# Step 3: 处理边框
|
| 242 |
+
if thickness > 0:
|
| 243 |
+
# 绘制矩形四条边框,连接四个圆角
|
| 244 |
+
cv2.line(img, (x1 + corner_radius, y1), (x2 - corner_radius, y1), color, thickness) # 上边
|
| 245 |
+
cv2.line(img, (x1 + corner_radius, y2), (x2 - corner_radius, y2), color, thickness) # 下边
|
| 246 |
+
cv2.line(img, (x1, y1 + corner_radius), (x1, y2 - corner_radius), color, thickness) # 左边
|
| 247 |
+
cv2.line(img, (x2, y1 + corner_radius), (x2, y2 - corner_radius), color, thickness) # 右边
|
| 248 |
+
|
| 249 |
+
def visualize_element(self, img, color=(0, 255, 0), line=3, show=False, ratio=1, expand_size=5, corner_radius=20,
|
| 250 |
+
loc=None):
|
| 251 |
+
# 调整线条粗细,根据缩放比例
|
| 252 |
+
loc = self.adjust_loc(ratio=ratio, expand_size=expand_size)
|
| 253 |
+
if loc is None:
|
| 254 |
+
loc = [0, 0, 0, 0]
|
| 255 |
+
adjusted_thickness = int(line * ratio)
|
| 256 |
+
if adjusted_thickness < 1:
|
| 257 |
+
adjusted_thickness = 1 # 确保最小粗细为1
|
| 258 |
+
|
| 259 |
+
# 调用通用的绘制带扩展的圆角矩形方法
|
| 260 |
+
self.draw_and_expand_rounded_rectangle(img, loc, color, adjusted_thickness, expand_size, corner_radius)
|
| 261 |
+
|
| 262 |
+
# 显示图像(可选)
|
| 263 |
if show:
|
| 264 |
cv2.imshow('element', img)
|
| 265 |
cv2.waitKey(0)
|
| 266 |
cv2.destroyWindow('element')
|
| 267 |
+
|
| 268 |
+
def calculate_text_height(self, font_title, font_text, title, text, bubble_width, inner_padding):
|
| 269 |
+
"""
|
| 270 |
+
计算文本内容的高度,包括标题和正文
|
| 271 |
+
"""
|
| 272 |
+
# 创建临时 PIL 图像用于计算文本高度
|
| 273 |
+
temp_img = Image.new("RGB", (bubble_width, 500), (255, 255, 255))
|
| 274 |
+
draw = ImageDraw.Draw(temp_img)
|
| 275 |
+
|
| 276 |
+
# 计算标题的高度
|
| 277 |
+
title_height = draw.textbbox((0, 0), title, font=font_title)[3] - \
|
| 278 |
+
draw.textbbox((0, 0), title, font=font_title)[1]
|
| 279 |
+
|
| 280 |
+
# 处理正文的自动换行
|
| 281 |
+
words = text.split(' ')
|
| 282 |
+
current_line = ""
|
| 283 |
+
lines = []
|
| 284 |
+
max_text_width = bubble_width - 2 * inner_padding
|
| 285 |
+
|
| 286 |
+
for word in words:
|
| 287 |
+
test_line = current_line + word + " "
|
| 288 |
+
text_bbox = draw.textbbox((0, 0), test_line, font=font_text)
|
| 289 |
+
text_width = text_bbox[2] - text_bbox[0]
|
| 290 |
+
|
| 291 |
+
if text_width < max_text_width:
|
| 292 |
+
current_line = test_line
|
| 293 |
+
else:
|
| 294 |
+
lines.append(current_line)
|
| 295 |
+
current_line = word + " "
|
| 296 |
+
|
| 297 |
+
# 添加最后一行
|
| 298 |
+
lines.append(current_line)
|
| 299 |
+
|
| 300 |
+
# 计算正文高度
|
| 301 |
+
text_height = len(lines) * (draw.textbbox((0, 0), lines[0], font=font_text)[3] -
|
| 302 |
+
draw.textbbox((0, 0), lines[0], font=font_text)[1]) + len(lines) * 5
|
| 303 |
+
|
| 304 |
+
# 计算总高度(标题 + 正文 + 内边距)
|
| 305 |
+
total_height = title_height + text_height + 2 * inner_padding + 50
|
| 306 |
+
|
| 307 |
+
return total_height
|
| 308 |
+
|
| 309 |
+
def write_text(self, img, bubble_top_left, font_title, font_text, title, text, bubble_width, inner_padding):
|
| 310 |
+
"""
|
| 311 |
+
在对话框内绘制标题和正文内容
|
| 312 |
+
"""
|
| 313 |
+
# 确保文本和对话框边缘有内边距
|
| 314 |
+
text_area_top_left = (bubble_top_left[0] + inner_padding, bubble_top_left[1] + inner_padding - 15)
|
| 315 |
+
|
| 316 |
+
# 将 OpenCV 图像转换为 PIL 图像
|
| 317 |
+
img_pil = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
|
| 318 |
+
|
| 319 |
+
# 创建 ImageDraw 对象用于绘制文字
|
| 320 |
+
draw = ImageDraw.Draw(img_pil)
|
| 321 |
+
|
| 322 |
+
# 绘制标题
|
| 323 |
+
draw.text((text_area_top_left[0], text_area_top_left[1]), title, font=font_title, fill=(255, 255, 255))
|
| 324 |
+
|
| 325 |
+
# 处理正文自动换行
|
| 326 |
+
text_start_y = text_area_top_left[1] + font_title.size + 50 # 标题下面再留些空间给正文
|
| 327 |
+
max_text_width = bubble_width - 2 * inner_padding
|
| 328 |
+
lines = []
|
| 329 |
+
words = text.split(' ')
|
| 330 |
+
current_line = ""
|
| 331 |
+
|
| 332 |
+
for word in words:
|
| 333 |
+
# 检查当前行的宽度
|
| 334 |
+
test_line = current_line + word + " "
|
| 335 |
+
text_bbox = draw.textbbox((0, 0), test_line, font=font_text)
|
| 336 |
+
text_width = text_bbox[2] - text_bbox[0]
|
| 337 |
+
|
| 338 |
+
if text_width < max_text_width:
|
| 339 |
+
current_line = test_line
|
| 340 |
+
else:
|
| 341 |
+
# 当前行内容超出对话框宽度,换行
|
| 342 |
+
lines.append(current_line)
|
| 343 |
+
current_line = word + " "
|
| 344 |
+
|
| 345 |
+
# 添加最后一行
|
| 346 |
+
lines.append(current_line)
|
| 347 |
+
|
| 348 |
+
# 绘制每一行正文
|
| 349 |
+
for line in lines:
|
| 350 |
+
draw.text((text_area_top_left[0], text_start_y), line, font=font_text, fill=(255, 255, 255))
|
| 351 |
+
text_start_y += font_text.size + 5
|
| 352 |
+
|
| 353 |
+
# 将 PIL 图像转换回 OpenCV 图像(直接修改 img)
|
| 354 |
+
img[:] = cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)
|
| 355 |
+
|
| 356 |
+
def process_img(self, img, elements, texts, color=(0, 255, 0), line=3, alpha=0.7, expand_size=5,
|
| 357 |
+
corner_radius=20, show=False, ratio=1, padding=50, triangle_height=0, inner_padding=100,
|
| 358 |
+
font_path_title="CDM/detect_merge/title.ttf", font_path_text="CDM/detect_merge/text.ttf",
|
| 359 |
+
font_size_title=70, font_size_text=50):
|
| 360 |
+
|
| 361 |
+
# --------------画所有边框+黑色半透明处理剩余部分----------------------
|
| 362 |
+
|
| 363 |
+
black_block_start = time.process_time()
|
| 364 |
+
|
| 365 |
+
# 创建一个全黑遮罩(用于透明处理)
|
| 366 |
+
mask = np.zeros_like(img, dtype=np.uint8)
|
| 367 |
+
|
| 368 |
+
# 遍历每个元素并绘制圆角矩形,排除这些区域
|
| 369 |
+
for element in elements:
|
| 370 |
+
loc = element.adjust_loc(ratio=ratio, expand_size=expand_size)
|
| 371 |
+
# 调用通用的绘制带扩展的圆角矩形方法,在遮罩上扣除这些区域
|
| 372 |
+
self.draw_and_expand_rounded_rectangle(mask, loc, (255, 255, 255), -1, expand_size, corner_radius)
|
| 373 |
+
|
| 374 |
+
# 创建一个全黑的图像,用于制作黑色遮罩
|
| 375 |
+
overlay = np.zeros_like(img, dtype=np.uint8)
|
| 376 |
+
overlay[:] = (0, 0, 0) # 这是一个全黑的遮罩
|
| 377 |
+
|
| 378 |
+
# 将 overlay 和 img 混合,但根据 mask 的黑色区域应用透明效果,白色区域保持原样
|
| 379 |
+
img_with_overlay = cv2.addWeighted(img, 1 - alpha, overlay, alpha, 0) # 将黑色透明度应用到整个图像
|
| 380 |
+
|
| 381 |
+
# 使用 mask 保留元素区域的原始图像
|
| 382 |
+
result = cv2.bitwise_and(img, mask) # 仅���留元素区域(白色部分)
|
| 383 |
+
result += cv2.bitwise_and(img_with_overlay, cv2.bitwise_not(mask)) # 将黑色透明遮罩应用到非元素区域(黑色部分)
|
| 384 |
+
|
| 385 |
+
# 将结果应用到 img 上
|
| 386 |
+
img[:, :, :] = result
|
| 387 |
+
|
| 388 |
+
# 为每个元素再绘制圆角矩形边框
|
| 389 |
+
for element in elements:
|
| 390 |
+
loc = element.adjust_loc(ratio=ratio, expand_size=expand_size)
|
| 391 |
+
element.visualize_element(img, color=color, line=line, show=show, ratio=ratio, loc=loc)
|
| 392 |
+
|
| 393 |
+
black_block_cost = time.process_time() - black_block_start
|
| 394 |
+
|
| 395 |
+
# print("绘制带黑色遮罩的框选component的圆角block花费:%2.2f s" % black_block_cost)
|
| 396 |
+
|
| 397 |
+
# -----------------------绘制信息部分----------------------------------
|
| 398 |
+
|
| 399 |
+
write_text_in_block = time.process_time()
|
| 400 |
+
|
| 401 |
+
# 获取图像的宽度和高度
|
| 402 |
+
img_height, img_width = img.shape[:2]
|
| 403 |
+
|
| 404 |
+
# 获取标题和正文的显示信息
|
| 405 |
+
title = "· " + elements[0].label
|
| 406 |
+
df = pd.DataFrame(texts)
|
| 407 |
+
df_unique = df.drop_duplicates(subset='label', keep='first')
|
| 408 |
+
text = df_unique[df_unique['label'] == elements[0].label]['segment'].values[0]
|
| 409 |
+
text = text[0].upper() + text[1:]
|
| 410 |
+
|
| 411 |
+
# 加载字体
|
| 412 |
+
font_title = ImageFont.truetype(font_path_title, font_size_title)
|
| 413 |
+
font_text = ImageFont.truetype(font_path_text, font_size_text)
|
| 414 |
+
|
| 415 |
+
# 计算所有元素的调整后位置
|
| 416 |
+
locs = [e.adjust_loc(ratio=ratio, expand_size=expand_size) for e in elements]
|
| 417 |
+
|
| 418 |
+
# 获取所有元素的上边界(y1)和下边界(y2)
|
| 419 |
+
# 并添加图片的上边界(0)和下边界(img_height)作为特殊的"元素"
|
| 420 |
+
y_positions = []
|
| 421 |
+
|
| 422 |
+
for loc in locs:
|
| 423 |
+
y_positions.append((loc[1], 'element_top')) # 元素的上边界
|
| 424 |
+
y_positions.append((loc[3], 'element_bottom')) # 元素的下边界
|
| 425 |
+
|
| 426 |
+
# 添加图片的上边界和下边界
|
| 427 |
+
y_positions.append((0, 'image_top'))
|
| 428 |
+
y_positions.append((img_height, 'image_bottom'))
|
| 429 |
+
|
| 430 |
+
# 按 Y 坐标排序
|
| 431 |
+
y_positions.sort(key=lambda x: x[0])
|
| 432 |
+
|
| 433 |
+
# 找到所有的垂直空白区域
|
| 434 |
+
gaps = []
|
| 435 |
+
|
| 436 |
+
for i in range(len(y_positions) - 1):
|
| 437 |
+
y1, label1 = y_positions[i]
|
| 438 |
+
y2, label2 = y_positions[i + 1]
|
| 439 |
+
|
| 440 |
+
# 如果两个位置之间有空隙
|
| 441 |
+
if y2 > y1:
|
| 442 |
+
gap_height = y2 - y1
|
| 443 |
+
gap = {
|
| 444 |
+
'start': y1,
|
| 445 |
+
'end': y2,
|
| 446 |
+
'height': gap_height,
|
| 447 |
+
'above': label1,
|
| 448 |
+
'below': label2
|
| 449 |
+
}
|
| 450 |
+
gaps.append(gap)
|
| 451 |
+
|
| 452 |
+
# 找到高度最大的空白区域
|
| 453 |
+
largest_gap = max(gaps, key=lambda x: x['height'])
|
| 454 |
+
|
| 455 |
+
# 判断最大的空白区域是否在元素和图片边界之间,还是在元素之间
|
| 456 |
+
is_between_element_and_border = False
|
| 457 |
+
is_between_elements = False
|
| 458 |
+
|
| 459 |
+
if largest_gap['above'] == 'image_top' or largest_gap['below'] == 'image_bottom':
|
| 460 |
+
is_between_element_and_border = True
|
| 461 |
+
elif largest_gap['above'] == 'element_bottom' and largest_gap['below'] == 'element_top':
|
| 462 |
+
is_between_elements = True
|
| 463 |
+
|
| 464 |
+
# 计算文本框的宽度
|
| 465 |
+
bubble_width = img_width - 2 * padding
|
| 466 |
+
|
| 467 |
+
# 计算文本框的高度
|
| 468 |
+
bubble_height = self.calculate_text_height(font_title, font_text, title, text, bubble_width, inner_padding)
|
| 469 |
+
|
| 470 |
+
# 确保文本框的高度不超过最大空白区域的高度减去两倍的内边距
|
| 471 |
+
max_bubble_height = largest_gap['height'] - 2 * padding
|
| 472 |
+
if bubble_height > max_bubble_height:
|
| 473 |
+
bubble_height = max_bubble_height
|
| 474 |
+
|
| 475 |
+
# 根据判断结果确定文本框的位置
|
| 476 |
+
if is_between_element_and_border:
|
| 477 |
+
# 文本框靠近对应的元素
|
| 478 |
+
|
| 479 |
+
if largest_gap['above'] == 'image_top':
|
| 480 |
+
# 空白区域在顶部,文本框在第一个元素的上方
|
| 481 |
+
ref_element = min(elements, key=lambda e: e.adjust_loc(ratio=ratio, expand_size=expand_size)[1])
|
| 482 |
+
loc = ref_element.adjust_loc(ratio=ratio, expand_size=expand_size)
|
| 483 |
+
y1 = loc[1]
|
| 484 |
+
|
| 485 |
+
bubble_top = y1 - triangle_height - padding - bubble_height
|
| 486 |
+
bubble_left = padding
|
| 487 |
+
elif largest_gap['below'] == 'image_bottom':
|
| 488 |
+
# 空白区域在底部,文本框在最后一个元素的下方
|
| 489 |
+
ref_element = max(elements, key=lambda e: e.adjust_loc(ratio=ratio, expand_size=expand_size)[3])
|
| 490 |
+
loc = ref_element.adjust_loc(ratio=ratio, expand_size=expand_size)
|
| 491 |
+
y2 = loc[3]
|
| 492 |
+
|
| 493 |
+
bubble_top = y2 + triangle_height + padding
|
| 494 |
+
bubble_left = padding
|
| 495 |
+
|
| 496 |
+
bubble_top_left = (bubble_left, bubble_top)
|
| 497 |
+
bubble_bottom_right = (bubble_left + bubble_width, bubble_top + bubble_height)
|
| 498 |
+
|
| 499 |
+
elif is_between_elements:
|
| 500 |
+
# 文本框在元素之间,垂直居中放置在最大空白区域内
|
| 501 |
+
gap_start = largest_gap['start']
|
| 502 |
+
gap_end = largest_gap['end']
|
| 503 |
+
|
| 504 |
+
bubble_top = gap_start + (gap_end - gap_start - bubble_height) / 2
|
| 505 |
+
bubble_left = padding
|
| 506 |
+
|
| 507 |
+
bubble_top_left = (bubble_left, bubble_top)
|
| 508 |
+
bubble_bottom_right = (bubble_left + bubble_width, bubble_top + bubble_height)
|
| 509 |
+
|
| 510 |
+
else:
|
| 511 |
+
# 如果没有符合条件的空白区域,默认将文本框放在图片的顶部
|
| 512 |
+
bubble_top_left = (padding, padding)
|
| 513 |
+
bubble_bottom_right = (bubble_top_left[0] + bubble_width, bubble_top_left[1] + bubble_height)
|
| 514 |
+
|
| 515 |
+
# 确保文本框不会超出图片的顶部或底部边界
|
| 516 |
+
if bubble_top_left[1] < 0:
|
| 517 |
+
bubble_top_left = (bubble_top_left[0], padding)
|
| 518 |
+
bubble_bottom_right = (bubble_bottom_right[0], bubble_top_left[1] + bubble_height)
|
| 519 |
+
elif bubble_bottom_right[1] > img_height:
|
| 520 |
+
bubble_bottom_right = (bubble_bottom_right[0], img_height - padding)
|
| 521 |
+
bubble_top_left = (bubble_top_left[0], bubble_bottom_right[1] - bubble_height)
|
| 522 |
+
|
| 523 |
+
# 绘制圆角矩形作为对话框
|
| 524 |
+
self.draw_and_expand_rounded_rectangle(
|
| 525 |
+
img,
|
| 526 |
+
[bubble_top_left[0], bubble_top_left[1], bubble_bottom_right[0], bubble_bottom_right[1]],
|
| 527 |
+
color,
|
| 528 |
+
corner_radius=50
|
| 529 |
+
)
|
| 530 |
+
|
| 531 |
+
# 对话框内写入文本
|
| 532 |
+
self.write_text(img, bubble_top_left, font_title, font_text, title, text, bubble_width, inner_padding)
|
| 533 |
+
|
| 534 |
+
# # 计算所有元素的调整后位置
|
| 535 |
+
# locs = [e.adjust_loc(ratio=ratio, expand_size=expand_size) for e in elements]
|
| 536 |
+
#
|
| 537 |
+
# # 计算元素组的包围框
|
| 538 |
+
# min_y1 = min(loc[1] for loc in locs)
|
| 539 |
+
# max_y2 = max(loc[3] for loc in locs)
|
| 540 |
+
#
|
| 541 |
+
# # 计算元素组到图片上下边界的距离
|
| 542 |
+
# top_distance_group = min_y1 # 元素组上边到图片上边界的距离
|
| 543 |
+
# bottom_distance_group = img_height - max_y2 # 元素组下边到图片下边界的距离
|
| 544 |
+
#
|
| 545 |
+
# if top_distance_group > bottom_distance_group:
|
| 546 |
+
# # 如果元素组上方空间更大,选择最靠近上边界的元素
|
| 547 |
+
# ref_element = min(elements, key=lambda e: e.adjust_loc(ratio=ratio, expand_size=expand_size)[1])
|
| 548 |
+
# else:
|
| 549 |
+
# # 否则,选择最靠近下边界的元素
|
| 550 |
+
# ref_element = max(elements, key=lambda e: e.adjust_loc(ratio=ratio, expand_size=expand_size)[3])
|
| 551 |
+
#
|
| 552 |
+
# # 使用参考元素进行后续操作
|
| 553 |
+
# loc = ref_element.adjust_loc(ratio=ratio, expand_size=expand_size)
|
| 554 |
+
# # 计算每个扩展后边界到图片边界的距离
|
| 555 |
+
# left_distance = loc[0] # 左边到图像左边界的距离
|
| 556 |
+
# right_distance = img_width - loc[2] # 右边到图像右边界的距离
|
| 557 |
+
# top_distance = loc[1] # 上边到图像上边界的距离
|
| 558 |
+
# bottom_distance = img_height - loc[3] # 下边到图像下边界的距离
|
| 559 |
+
#
|
| 560 |
+
# # 存储每个边界的距离
|
| 561 |
+
# distances = {
|
| 562 |
+
# 'left': left_distance,
|
| 563 |
+
# 'right': right_distance,
|
| 564 |
+
# 'top': top_distance,
|
| 565 |
+
# 'bottom': bottom_distance
|
| 566 |
+
# }
|
| 567 |
+
#
|
| 568 |
+
# # 计算对话框宽度(接近 img 的宽度,但稍微小于 img 宽度)
|
| 569 |
+
# bubble_width = img_width - 2 * padding
|
| 570 |
+
# x1, y1, x2, y2 = loc
|
| 571 |
+
#
|
| 572 |
+
# # 计算文本框的高度
|
| 573 |
+
# bubble_height = self.calculate_text_height(font_title, font_text, title, text, bubble_width, inner_padding)
|
| 574 |
+
#
|
| 575 |
+
# # 根据元素位置绘制对话框
|
| 576 |
+
# if distances['top'] > distances['bottom']:
|
| 577 |
+
# # 对话框的位置:在元素上方
|
| 578 |
+
# bubble_top_left = (padding, y1 - triangle_height - padding - bubble_height)
|
| 579 |
+
# bubble_bottom_right = (bubble_width + padding, y1 - triangle_height - padding)
|
| 580 |
+
# else:
|
| 581 |
+
# # 对话框的位置:在元素下方
|
| 582 |
+
# bubble_top_left = (padding, y2 + triangle_height + padding)
|
| 583 |
+
# bubble_bottom_right = (bubble_width + padding, y2 + triangle_height + padding + bubble_height)
|
| 584 |
+
#
|
| 585 |
+
# # 绘制圆角矩形作为对话框
|
| 586 |
+
# self.draw_and_expand_rounded_rectangle(
|
| 587 |
+
# img,
|
| 588 |
+
# [bubble_top_left[0], bubble_top_left[1], bubble_bottom_right[0], bubble_bottom_right[1]],
|
| 589 |
+
# color,
|
| 590 |
+
# corner_radius=50
|
| 591 |
+
# )
|
| 592 |
+
#
|
| 593 |
+
# # 对话框内写入文本
|
| 594 |
+
# self.write_text(img, bubble_top_left, font_title, font_text, title, text, bubble_width, inner_padding)
|
| 595 |
+
|
| 596 |
+
write_in_block_cost = time.process_time() - write_text_in_block
|
| 597 |
+
|
| 598 |
+
# print("绘制文本展示block+写入文字花费时间:%2.2f s" % write_in_block_cost)
|
| 599 |
+
|
| 600 |
+
|
| 601 |
+
|
| 602 |
+
|
| 603 |
+
|
| 604 |
+
# =====================================================
|
| 605 |
+
|
| 606 |
+
|
| 607 |
+
|
| 608 |
+
|
| 609 |
+
|
| 610 |
+
# # 如果这张图只有一个element
|
| 611 |
+
# if len(elements) == 1:
|
| 612 |
+
# loc = elements[0].adjust_loc(ratio=ratio, expand_size=expand_size)
|
| 613 |
+
# # 计算每个扩展后边界到图片边界的距离
|
| 614 |
+
# left_distance = loc[0] # 左边到图像左边界的距离
|
| 615 |
+
# right_distance = img_width - loc[2] # 右边到图像右边界的距离
|
| 616 |
+
# top_distance = loc[1] # 上边到图像上边界的距离
|
| 617 |
+
# bottom_distance = img_height - loc[3] # 下边到图像下边界的距离
|
| 618 |
+
#
|
| 619 |
+
# # 存储每个边界的距离
|
| 620 |
+
# distances = {
|
| 621 |
+
# 'left': left_distance,
|
| 622 |
+
# 'right': right_distance,
|
| 623 |
+
# 'top': top_distance,
|
| 624 |
+
# 'bottom': bottom_distance
|
| 625 |
+
# }
|
| 626 |
+
#
|
| 627 |
+
# # 计算对话框宽度(接近 img 的宽度,但稍微小于 img 宽度)
|
| 628 |
+
# bubble_width = img_width - 2 * padding
|
| 629 |
+
# x1, y1, x2, y2 = loc
|
| 630 |
+
#
|
| 631 |
+
# # 计算文本框的高度
|
| 632 |
+
# bubble_height = self.calculate_text_height(font_title, font_text, title, text, bubble_width, inner_padding)
|
| 633 |
+
#
|
| 634 |
+
# # 根据元素位置绘制对话框
|
| 635 |
+
# if distances['top'] > distances['bottom']:
|
| 636 |
+
# # 对话框的位置:在元素上方
|
| 637 |
+
# bubble_top_left = (padding, y1 - triangle_height - padding - bubble_height)
|
| 638 |
+
# bubble_bottom_right = (bubble_width + padding, y1 - triangle_height - padding)
|
| 639 |
+
# # # 三角形的底边中心位置 (等边三角形)
|
| 640 |
+
# # triangle_base_y = bubble_bottom_right[1]
|
| 641 |
+
# # triangle_center_x = (x1 + x2) // 2
|
| 642 |
+
# # # 三角形顶点朝下
|
| 643 |
+
# # triangle_tip_y = triangle_base_y + (triangle_height - 10)
|
| 644 |
+
# else:
|
| 645 |
+
# # 对话框的位置:在元素下方
|
| 646 |
+
# bubble_top_left = (padding, y2 + triangle_height + padding)
|
| 647 |
+
# bubble_bottom_right = (bubble_width + padding, y2 + triangle_height + padding + bubble_height)
|
| 648 |
+
# # # 三角形的底边中心位置 (等边三角形)
|
| 649 |
+
# # triangle_base_y = bubble_top_left[1]
|
| 650 |
+
# # triangle_center_x = (x1 + x2) // 2
|
| 651 |
+
# # # 三角形顶点朝上
|
| 652 |
+
# # triangle_tip_y = triangle_base_y - (triangle_height - 10)
|
| 653 |
+
#
|
| 654 |
+
# # # 三角形底边长度等于高度,所以底边是 [triangle_height] 的两倍
|
| 655 |
+
# # half_base = triangle_height // 2 + 5
|
| 656 |
+
# #
|
| 657 |
+
# # # 绘制等边三角形
|
| 658 |
+
# # triangle_points = np.array([
|
| 659 |
+
# # [triangle_center_x - half_base, triangle_base_y], # 三角形左边点
|
| 660 |
+
# # [triangle_center_x + half_base, triangle_base_y], # 三角形右边点
|
| 661 |
+
# # [triangle_center_x, triangle_tip_y] # 三角形顶点
|
| 662 |
+
# # ])
|
| 663 |
+
# # cv2.fillPoly(img, [triangle_points], color)
|
| 664 |
+
#
|
| 665 |
+
# # 绘制圆角矩形作为对话框
|
| 666 |
+
# self.draw_and_expand_rounded_rectangle(img,
|
| 667 |
+
# [bubble_top_left[0], bubble_top_left[1], bubble_bottom_right[0],
|
| 668 |
+
# bubble_bottom_right[1]], color, corner_radius=50)
|
| 669 |
+
#
|
| 670 |
+
# # 对话框内写入文本
|
| 671 |
+
# self.write_text(img, bubble_top_left, font_title, font_text, title, text, bubble_width, inner_padding)
|
| 672 |
+
#
|
| 673 |
+
# # else:
|
CDM/detect_merge/merge.py
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
|
|
| 1 |
import json
|
|
|
|
|
|
|
| 2 |
import cv2
|
| 3 |
import numpy as np
|
| 4 |
from os.path import join as pjoin
|
|
@@ -13,6 +16,13 @@ import torch
|
|
| 13 |
|
| 14 |
import CDM.detect_compo.lib_ip.ip_preprocessing as pre
|
| 15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
# ----------------- load pre-trained classification model ----------------
|
| 17 |
|
| 18 |
# model = models.resnet18().to('cpu')
|
|
@@ -77,6 +87,35 @@ def show_one_element(org_img, eles, ratio, show=False, win_name='element', wait_
|
|
| 77 |
return all_img
|
| 78 |
|
| 79 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
def save_elements(output_file, elements, img_shape, ratio=1):
|
| 81 |
components = {'compos': [], 'img_shape': img_shape}
|
| 82 |
for i, ele in enumerate(elements):
|
|
@@ -356,6 +395,6 @@ def merge(img_path, compo_path, text_path, merge_root=None, is_paragraph=False,
|
|
| 356 |
name = img_path.replace('\\', '/').split('/')[-1][:-4]
|
| 357 |
components = save_elements(pjoin(merge_root, name + '.json'), elements, img_resize.shape)
|
| 358 |
cv2.imwrite(pjoin(merge_root, name + '.jpg'), board)
|
| 359 |
-
print('[Merge Completed] Input: %s Output: %s' % (img_path, pjoin(merge_root, name + '.jpg')))
|
| 360 |
return board, components
|
| 361 |
# return this_ic_time, this_ts_time
|
|
|
|
| 1 |
+
import copy
|
| 2 |
import json
|
| 3 |
+
import math
|
| 4 |
+
|
| 5 |
import cv2
|
| 6 |
import numpy as np
|
| 7 |
from os.path import join as pjoin
|
|
|
|
| 16 |
|
| 17 |
import CDM.detect_compo.lib_ip.ip_preprocessing as pre
|
| 18 |
|
| 19 |
+
ColorMap = {'Name': (51, 199, 255), 'Birthday': (255, 174, 200), 'Address': (173, 103, 247), 'Phone': (19, 127, 9),
|
| 20 |
+
'Email': (0, 205, 255), 'Contacts': (255, 174, 0), 'Location': (255, 195, 0), 'Photos': (133, 46, 182),
|
| 21 |
+
'Voices': (182, 255, 0), 'Financial info': (164, 19, 19), 'IP': (5, 226, 206), 'Cookies': (13, 131, 202),
|
| 22 |
+
'Social media': (164, 25, 166), 'Profile': (95, 146, 44), 'Gender': (252, 81, 81)}
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
|
| 26 |
# ----------------- load pre-trained classification model ----------------
|
| 27 |
|
| 28 |
# model = models.resnet18().to('cpu')
|
|
|
|
| 87 |
return all_img
|
| 88 |
|
| 89 |
|
| 90 |
+
def show_one_element_class(org_img, eles, ratio, summarized_data, show=False, win_name='element', wait_key=0, shown_resize=None, line=3):
|
| 91 |
+
all_img = []
|
| 92 |
+
eles_copy = copy.copy(eles)
|
| 93 |
+
for ele in eles:
|
| 94 |
+
if any(ele is ele_copy for ele_copy in eles_copy):
|
| 95 |
+
ele_group = [ele]
|
| 96 |
+
img = org_img.copy()
|
| 97 |
+
color = ColorMap[ele.label]
|
| 98 |
+
# ele.visualize_element(img=img, color=color, line=line, ratio=ratio)
|
| 99 |
+
for ele0 in eles:
|
| 100 |
+
if ele0 != ele and ele.label == ele0.label:
|
| 101 |
+
ele_group.append(ele0)
|
| 102 |
+
eles_copy.remove(ele0)
|
| 103 |
+
ele.process_img(img=img, elements=ele_group, texts=summarized_data, color=color, ratio=ratio, line=line)
|
| 104 |
+
|
| 105 |
+
img_resize = img
|
| 106 |
+
all_img.append(img_resize)
|
| 107 |
+
if shown_resize is not None:
|
| 108 |
+
img_resize = cv2.resize(img, shown_resize)
|
| 109 |
+
if show:
|
| 110 |
+
cv2.imshow(win_name, img_resize)
|
| 111 |
+
cv2.waitKey(wait_key)
|
| 112 |
+
if wait_key == 0:
|
| 113 |
+
cv2.destroyWindow(win_name)
|
| 114 |
+
else:
|
| 115 |
+
continue
|
| 116 |
+
return all_img
|
| 117 |
+
|
| 118 |
+
|
| 119 |
def save_elements(output_file, elements, img_shape, ratio=1):
|
| 120 |
components = {'compos': [], 'img_shape': img_shape}
|
| 121 |
for i, ele in enumerate(elements):
|
|
|
|
| 395 |
name = img_path.replace('\\', '/').split('/')[-1][:-4]
|
| 396 |
components = save_elements(pjoin(merge_root, name + '.json'), elements, img_resize.shape)
|
| 397 |
cv2.imwrite(pjoin(merge_root, name + '.jpg'), board)
|
| 398 |
+
# print('[Merge Completed] Input: %s Output: %s' % (img_path, pjoin(merge_root, name + '.jpg')))
|
| 399 |
return board, components
|
| 400 |
# return this_ic_time, this_ts_time
|
CDM/run_single.py
CHANGED
|
@@ -12,27 +12,27 @@ import CDM.detect_classify.classification as clf
|
|
| 12 |
import pandas as pd
|
| 13 |
import openai
|
| 14 |
|
| 15 |
-
def summarize_segment(segment):
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
|
| 37 |
def resize_height_by_longest_edge(img_path, resize_length=800):
|
| 38 |
org = cv2.imread(img_path)
|
|
@@ -47,6 +47,7 @@ def run_single_img(input_img, output_root, segment_root):
|
|
| 47 |
# output_root = "./result_classification"
|
| 48 |
# segment_root = '../scrutinizing_alexa/txt'
|
| 49 |
|
|
|
|
| 50 |
if os.path.exists(output_root):
|
| 51 |
shutil.rmtree(output_root)
|
| 52 |
os.makedirs(output_root)
|
|
@@ -111,6 +112,8 @@ def run_single_img(input_img, output_root, segment_root):
|
|
| 111 |
resize_by_height=resized_height, show=False)
|
| 112 |
cd_time_cost_all.append(this_cd_time_cost)
|
| 113 |
|
|
|
|
|
|
|
| 114 |
if is_merge:
|
| 115 |
import CDM.detect_merge.merge as merge
|
| 116 |
|
|
@@ -127,7 +130,7 @@ def run_single_img(input_img, output_root, segment_root):
|
|
| 127 |
merge_path = pjoin(output_root, 'merge', str(index) + '.json')
|
| 128 |
merge_json = json.load(open(merge_path, 'r'))
|
| 129 |
os.makedirs(pjoin(output_root, 'classification', 'GUI'), exist_ok=True)
|
| 130 |
-
this_time_cost_ic, this_time_cost_ts, output_data,
|
| 131 |
segment_root, merge_json,
|
| 132 |
output_data,
|
| 133 |
resize_by_height=resize_by_height, clf_model="ViT")
|
|
@@ -137,7 +140,9 @@ def run_single_img(input_img, output_root, segment_root):
|
|
| 137 |
|
| 138 |
this_img_time_cost = time.process_time() - this_img_start_time
|
| 139 |
img_time_cost_all.append(this_img_time_cost)
|
| 140 |
-
print("time cost for this image: %2.2f s" % this_img_time_cost)
|
|
|
|
|
|
|
| 141 |
|
| 142 |
if os.path.isfile(output_root + '/output.csv'):
|
| 143 |
output_data.to_csv(output_root + '/output.csv', index=False, mode='a', header=False)
|
|
@@ -155,8 +160,8 @@ def run_single_img(input_img, output_root, segment_root):
|
|
| 155 |
# print("average text selection processing time cost for this app: %2.2f s" % avg_ts_time_cost)
|
| 156 |
# print("average screenshot processing time cost for this app: %2.2f s" % avg_time_cost)
|
| 157 |
|
| 158 |
-
short_output_data = output_data[['id', 'label', 'text']].copy()
|
| 159 |
-
short_output_data = short_output_data.rename(columns={'text': 'segment'})
|
| 160 |
|
| 161 |
# summarize segments:
|
| 162 |
|
|
@@ -182,34 +187,34 @@ def run_single_img(input_img, output_root, segment_root):
|
|
| 182 |
#
|
| 183 |
# short_output_data.loc[index, 'segment'] = shortened_seg
|
| 184 |
|
| 185 |
-
original_output = []
|
| 186 |
-
retries = 3
|
| 187 |
-
summarized_data = [] # List to hold summarized rows
|
| 188 |
-
for index, row in short_output_data.iterrows():
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
summarized_output_data = pd.DataFrame(summarized_data)
|
| 211 |
-
original_output_data = pd.DataFrame(original_output)
|
| 212 |
-
|
| 213 |
-
return
|
| 214 |
|
| 215 |
|
|
|
|
| 12 |
import pandas as pd
|
| 13 |
import openai
|
| 14 |
|
| 15 |
+
# def summarize_segment(segment):
|
| 16 |
+
# openai.api_key = os.environ.get('openai_key')
|
| 17 |
+
#
|
| 18 |
+
# prompt = f"Shorten this paragraph: \"{str(segment)}\"."
|
| 19 |
+
#
|
| 20 |
+
# response = openai.ChatCompletion.create(
|
| 21 |
+
# # engine="text-davinci-002",
|
| 22 |
+
# model="gpt-3.5-turbo",
|
| 23 |
+
# messages=[
|
| 24 |
+
# # {"role": "system", "content": "You are a helpful assistant."},
|
| 25 |
+
# {"role": "user", "content": prompt}
|
| 26 |
+
# ],
|
| 27 |
+
# max_tokens=400,
|
| 28 |
+
# n=1,
|
| 29 |
+
# stop=None,
|
| 30 |
+
# temperature=0,
|
| 31 |
+
# )
|
| 32 |
+
#
|
| 33 |
+
# shortened_segment = response.choices[0].message['content']
|
| 34 |
+
#
|
| 35 |
+
# return shortened_segment
|
| 36 |
|
| 37 |
def resize_height_by_longest_edge(img_path, resize_length=800):
|
| 38 |
org = cv2.imread(img_path)
|
|
|
|
| 47 |
# output_root = "./result_classification"
|
| 48 |
# segment_root = '../scrutinizing_alexa/txt'
|
| 49 |
|
| 50 |
+
global output_boards
|
| 51 |
if os.path.exists(output_root):
|
| 52 |
shutil.rmtree(output_root)
|
| 53 |
os.makedirs(output_root)
|
|
|
|
| 112 |
resize_by_height=resized_height, show=False)
|
| 113 |
cd_time_cost_all.append(this_cd_time_cost)
|
| 114 |
|
| 115 |
+
detection_cost = time.process_time() - this_img_start_time
|
| 116 |
+
|
| 117 |
if is_merge:
|
| 118 |
import CDM.detect_merge.merge as merge
|
| 119 |
|
|
|
|
| 130 |
merge_path = pjoin(output_root, 'merge', str(index) + '.json')
|
| 131 |
merge_json = json.load(open(merge_path, 'r'))
|
| 132 |
os.makedirs(pjoin(output_root, 'classification', 'GUI'), exist_ok=True)
|
| 133 |
+
this_time_cost_ic, this_time_cost_ts, output_data, output_boards, classification_cost = clf.compo_classification(input_img, output_root,
|
| 134 |
segment_root, merge_json,
|
| 135 |
output_data,
|
| 136 |
resize_by_height=resize_by_height, clf_model="ViT")
|
|
|
|
| 140 |
|
| 141 |
this_img_time_cost = time.process_time() - this_img_start_time
|
| 142 |
img_time_cost_all.append(this_img_time_cost)
|
| 143 |
+
# print("time cost for this image: %2.2f s" % this_img_time_cost)
|
| 144 |
+
|
| 145 |
+
print("检测+分类共花费: %2.2f s" % (classification_cost + detection_cost))
|
| 146 |
|
| 147 |
if os.path.isfile(output_root + '/output.csv'):
|
| 148 |
output_data.to_csv(output_root + '/output.csv', index=False, mode='a', header=False)
|
|
|
|
| 160 |
# print("average text selection processing time cost for this app: %2.2f s" % avg_ts_time_cost)
|
| 161 |
# print("average screenshot processing time cost for this app: %2.2f s" % avg_time_cost)
|
| 162 |
|
| 163 |
+
# short_output_data = output_data[['id', 'label', 'text']].copy()
|
| 164 |
+
# short_output_data = short_output_data.rename(columns={'text': 'segment'})
|
| 165 |
|
| 166 |
# summarize segments:
|
| 167 |
|
|
|
|
| 187 |
#
|
| 188 |
# short_output_data.loc[index, 'segment'] = shortened_seg
|
| 189 |
|
| 190 |
+
# original_output = []
|
| 191 |
+
# retries = 3
|
| 192 |
+
# summarized_data = [] # List to hold summarized rows
|
| 193 |
+
# for index, row in short_output_data.iterrows():
|
| 194 |
+
# seg = row['segment']
|
| 195 |
+
# for i in range(retries):
|
| 196 |
+
# try:
|
| 197 |
+
# shortened_seg = summarize_segment(seg)
|
| 198 |
+
# break
|
| 199 |
+
# except openai.error.RateLimitError as e:
|
| 200 |
+
# if "overloaded" in str(e):
|
| 201 |
+
#
|
| 202 |
+
# sleep_time = 2 * (2 ** i) + 0.1
|
| 203 |
+
# # sleep_time = 3
|
| 204 |
+
# time.sleep(sleep_time)
|
| 205 |
+
# except Exception as e:
|
| 206 |
+
# # If you wish, you can print or log the exception details here without raising it
|
| 207 |
+
# print(e)
|
| 208 |
+
# else:
|
| 209 |
+
# # This part will be executed if the for loop doesn't hit 'break'
|
| 210 |
+
# shortened_seg = seg
|
| 211 |
+
#
|
| 212 |
+
# summarized_data.append({'id': row['id'], 'label': row['label'], 'segment': shortened_seg})
|
| 213 |
+
# original_output.append({'id': row['id'], 'label': row['label'], 'segment': seg[0].upper() + seg[1:]})
|
| 214 |
+
#
|
| 215 |
+
# summarized_output_data = pd.DataFrame(summarized_data)
|
| 216 |
+
# original_output_data = pd.DataFrame(original_output)
|
| 217 |
+
|
| 218 |
+
return output_boards
|
| 219 |
|
| 220 |
|
SEM/get_text.py
CHANGED
|
@@ -22,7 +22,21 @@ mark_txt = {'0':"/data_types.txt",
|
|
| 22 |
'14':"/thrid_party.txt",
|
| 23 |
'15':"/data_types.txt"}
|
| 24 |
|
| 25 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
type = 0
|
| 27 |
security = 0
|
| 28 |
right = 0
|
|
@@ -32,10 +46,26 @@ def write_text(title_list, pathName):
|
|
| 32 |
retention = 0
|
| 33 |
useData = 0
|
| 34 |
clean_title_list = []
|
|
|
|
| 35 |
for title in title_list:
|
| 36 |
if title.text != "•":
|
| 37 |
clean_title_list.append(title)
|
| 38 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
# print("title list:"+str(clean_title_list))
|
| 40 |
|
| 41 |
lastMark = ""
|
|
@@ -163,6 +193,41 @@ def write_text(title_list, pathName):
|
|
| 163 |
g.write("\n")
|
| 164 |
g.close()
|
| 165 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
return type,security,right,specialArea,specialGroup,update,retention,useData
|
| 167 |
|
| 168 |
def write_text_without_label(text, pathName):
|
|
|
|
| 22 |
'14':"/thrid_party.txt",
|
| 23 |
'15':"/data_types.txt"}
|
| 24 |
|
| 25 |
+
def process_content_outside_heading(content, pathName):
|
| 26 |
+
# 将内容转换为文本并进行预处理
|
| 27 |
+
soup = BeautifulSoup(content, 'html.parser')
|
| 28 |
+
text_content = soup.get_text(separator=' ', strip=True)
|
| 29 |
+
# 如果内容不为空,进行分类或其他处理
|
| 30 |
+
if text_content:
|
| 31 |
+
# 您可以在这里使用与标题相同的分类器进行分类
|
| 32 |
+
mark = clf.predict(tf.transform([text_content]))
|
| 33 |
+
# 将处理后的内容写入对应的文件
|
| 34 |
+
with open('./SEM/txt/'+pathName[:-5]+mark_txt.get(mark[0]), "a", encoding='utf-8') as f:
|
| 35 |
+
f.write(text_content)
|
| 36 |
+
f.write("\n")
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def write_text(title_list, pathName, soup):
|
| 40 |
type = 0
|
| 41 |
security = 0
|
| 42 |
right = 0
|
|
|
|
| 46 |
retention = 0
|
| 47 |
useData = 0
|
| 48 |
clean_title_list = []
|
| 49 |
+
|
| 50 |
for title in title_list:
|
| 51 |
if title.text != "•":
|
| 52 |
clean_title_list.append(title)
|
| 53 |
|
| 54 |
+
|
| 55 |
+
# # 处理第一个标题之前的内容
|
| 56 |
+
# if clean_title_list:
|
| 57 |
+
# first_title = clean_title_list[0]
|
| 58 |
+
# content_before_first_title = []
|
| 59 |
+
# for element in first_title.find_previous_siblings():
|
| 60 |
+
# content_before_first_title.insert(0, element) # 逆序插入,保持顺序
|
| 61 |
+
# content_before_first_title = ''.join([str(elem) for elem in content_before_first_title])
|
| 62 |
+
# # 处理标题外的内容
|
| 63 |
+
# process_content_outside_heading(content_before_first_title, pathName)
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
|
| 69 |
# print("title list:"+str(clean_title_list))
|
| 70 |
|
| 71 |
lastMark = ""
|
|
|
|
| 193 |
g.write("\n")
|
| 194 |
g.close()
|
| 195 |
|
| 196 |
+
# 处理标题之外的段落
|
| 197 |
+
remaining_soup = soup # 保留整个页面的 soup 结构
|
| 198 |
+
|
| 199 |
+
# 遍历标题列表,移除已经处理的标题和标题下的段落
|
| 200 |
+
for title in clean_title_list:
|
| 201 |
+
title.extract() # 移除每个标题及其下的段落
|
| 202 |
+
|
| 203 |
+
# 剩下的文本内容未被标题覆盖,进行同样的分类处理
|
| 204 |
+
removeUnneccessaryElements(remaining_soup)
|
| 205 |
+
remaining_segments = makeCoarseSegments(remaining_soup)
|
| 206 |
+
for seg in remaining_segments:
|
| 207 |
+
seg_clean = ' '.join(seg.split())
|
| 208 |
+
if len(seg_clean) != 0:
|
| 209 |
+
try:
|
| 210 |
+
mark = clf.predict(tf.transform([seg_clean]))
|
| 211 |
+
with open('./SEM/txt/' + pathName[:-5] + mark_txt.get(mark[0]), "a", encoding='utf-8') as f:
|
| 212 |
+
f.write(seg_clean)
|
| 213 |
+
f.write("\n")
|
| 214 |
+
f.close()
|
| 215 |
+
except Exception as e:
|
| 216 |
+
continue
|
| 217 |
+
|
| 218 |
+
# # 处理最后一个标题之后的内容
|
| 219 |
+
# if clean_title_list:
|
| 220 |
+
# last_title = clean_title_list[-1]
|
| 221 |
+
# content_after_last_title = []
|
| 222 |
+
# for element in last_title.next_siblings:
|
| 223 |
+
# content_after_last_title.append(element)
|
| 224 |
+
# content_after_last_title = ''.join([str(elem) for elem in content_after_last_title])
|
| 225 |
+
# # 处理标题外的内容
|
| 226 |
+
# process_content_outside_heading(content_after_last_title, pathName)
|
| 227 |
+
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
|
| 231 |
return type,security,right,specialArea,specialGroup,update,retention,useData
|
| 232 |
|
| 233 |
def write_text_without_label(text, pathName):
|
SEM/run_single_sem.py
CHANGED
|
@@ -28,18 +28,18 @@ def run_single_pp(file):
|
|
| 28 |
pathName = "1.html"
|
| 29 |
|
| 30 |
label = find_title_Label(file)
|
| 31 |
-
print("label: ", label)
|
| 32 |
-
print("The current file is:" + pathName)
|
| 33 |
|
| 34 |
# if pathName != '20.html':
|
| 35 |
# continue
|
| 36 |
|
| 37 |
para_start_time = time.process_time()
|
| 38 |
soup = BeautifulSoup(open(file,encoding='utf-8'), features="html.parser")
|
| 39 |
-
print("soup.contents: ", soup.contents)
|
| 40 |
title_list = soup.find_all(label)
|
| 41 |
# cleaning_txt()
|
| 42 |
-
print("title_list: ", title_list)
|
| 43 |
|
| 44 |
if not os.path.exists(result_root + pathName[:-5]):
|
| 45 |
os.mkdir(result_root + pathName[:-5])
|
|
@@ -53,7 +53,7 @@ def run_single_pp(file):
|
|
| 53 |
f.write(seg)
|
| 54 |
f.write("\n")
|
| 55 |
else:
|
| 56 |
-
write_text(title_list, pathName)
|
| 57 |
print("Paragraph level processing time: %2.2f s" % (time.process_time() - para_start_time))
|
| 58 |
|
| 59 |
for t in title_list:
|
|
|
|
| 28 |
pathName = "1.html"
|
| 29 |
|
| 30 |
label = find_title_Label(file)
|
| 31 |
+
# print("label: ", label)
|
| 32 |
+
# print("The current file is:" + pathName)
|
| 33 |
|
| 34 |
# if pathName != '20.html':
|
| 35 |
# continue
|
| 36 |
|
| 37 |
para_start_time = time.process_time()
|
| 38 |
soup = BeautifulSoup(open(file,encoding='utf-8'), features="html.parser")
|
| 39 |
+
# print("soup.contents: ", soup.contents)
|
| 40 |
title_list = soup.find_all(label)
|
| 41 |
# cleaning_txt()
|
| 42 |
+
# print("title_list: ", title_list)
|
| 43 |
|
| 44 |
if not os.path.exists(result_root + pathName[:-5]):
|
| 45 |
os.mkdir(result_root + pathName[:-5])
|
|
|
|
| 53 |
f.write(seg)
|
| 54 |
f.write("\n")
|
| 55 |
else:
|
| 56 |
+
write_text(title_list, pathName, soup)
|
| 57 |
print("Paragraph level processing time: %2.2f s" % (time.process_time() - para_start_time))
|
| 58 |
|
| 59 |
for t in title_list:
|
SEM/txt/1/children.txt
CHANGED
|
@@ -1 +1,2 @@
|
|
| 1 |
McDonald's is very sensitive to privacy issues. We are proud of our long-time commitment to our customers. McDonald’s does not intend to collect personal information from any person under the age of 18 years without the consent of a parent or legal guardian. We urge parents to regularly monitor and supervise their children's online activities.
|
|
|
|
|
|
| 1 |
McDonald's is very sensitive to privacy issues. We are proud of our long-time commitment to our customers. McDonald’s does not intend to collect personal information from any person under the age of 18 years without the consent of a parent or legal guardian. We urge parents to regularly monitor and supervise their children's online activities.
|
| 2 |
+
McDonald's is very sensitive to privacy issues. We are proud of our long-time commitment to our customers. McDonald’s does not intend to collect personal information from any person under the age of 18 years without the consent of a parent or legal guardian. We urge parents to regularly monitor and supervise their children's online activities.
|
SEM/txt/1/data_types.txt
CHANGED
|
@@ -35,3 +35,65 @@ You are in control of any personal information you provide to us. If, at any tim
|
|
| 35 |
Your personal information may be stored in different locations depending upon the reason for which you originally submitted the information. If you make an inquiry in relation to your personal information, the more information you can provide us about when you originally submitted your personal information, the quicker McDonald's will be able to retrieve your personal information. McDonald’s may require you to verify your identity by asking you to provide certain information about yourself and provide us with a declaration witnessed and signed by a Justice of Peace. Once your identity is verified, we will work to provide you with your requested information.
|
| 36 |
If you request, we will take all reasonable steps to delete your personal information, except where it is required for legal and compliance reasons. Deletion of information may result in McDonald's being unable to facilitate or provide you with information about certain transactions (including the uploading of, access to, and receipt of, content on a Website or App, and purchase transactions undertaken on a Website or App), other content, services or product information, upcoming promotions, competitions or event information, and/or provide certain content, products or services.
|
| 37 |
We are not responsible for removing your personal information from the lists of any third party who has previously been provided your information in accordance with this privacy policy.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
Your personal information may be stored in different locations depending upon the reason for which you originally submitted the information. If you make an inquiry in relation to your personal information, the more information you can provide us about when you originally submitted your personal information, the quicker McDonald's will be able to retrieve your personal information. McDonald’s may require you to verify your identity by asking you to provide certain information about yourself and provide us with a declaration witnessed and signed by a Justice of Peace. Once your identity is verified, we will work to provide you with your requested information.
|
| 36 |
If you request, we will take all reasonable steps to delete your personal information, except where it is required for legal and compliance reasons. Deletion of information may result in McDonald's being unable to facilitate or provide you with information about certain transactions (including the uploading of, access to, and receipt of, content on a Website or App, and purchase transactions undertaken on a Website or App), other content, services or product information, upcoming promotions, competitions or event information, and/or provide certain content, products or services.
|
| 37 |
We are not responsible for removing your personal information from the lists of any third party who has previously been provided your information in accordance with this privacy policy.
|
| 38 |
+
McDonald's Australia Limited ABN 43 008 496 928 (McDonald’s) and each of its independently owned franchisees ('McDonald’s Franchisees”) (collectively referred to as “McDonald’s”, “we”, “us” or “our”) are committed to respecting your personal information. Our privacy policy sets out how we collect, use, store and disclose your personal information. When you use our Websites, Apps, or provide your personal information to us, you consent to your personal information being collected, held, used and disclosed as set out in our privacy policy.
|
| 39 |
+
Information we collect and hold.
|
| 40 |
+
(collectively referred to as “Collection Channels”).
|
| 41 |
+
Personal information that McDonald’s collects and holds may include your name, email address, delivery address, date of birth, phone number, payment method, social media handles, images, audio and video of you, and other identifying information you choose to provide via a particular Collection Channel.
|
| 42 |
+
We also collect personal or anonymous information about you from other sources and sometimes combine that information with other information collected from you or from third parties for the purposes disclosed in this privacy policy.
|
| 43 |
+
McDonald’s will only collect or monitor any personal information about you as provided in this privacy policy.
|
| 44 |
+
Mobile platforms such as iOS and Android may define certain types of information or data that our Apps cannot access without your consent. Each platform has its own permissions system for obtaining your consent. For example, the iOS platform may alert you the first time an App wants your permission to access certain types of data (e.g. location services) and will provide you the option to consent to that request. Android devices may notify you of the permissions that an App seeks before you first use the App and your subsequent use of the App constitutes your consent. You can manage your platform level permissions via the Settings section on your device. For more information, please contact your device provider or refer to the user manual for your device.
|
| 45 |
+
You may contact McDonald’s with any queries via email: privacy@au.mcd.com or at McDonald's Australia Limited (Attention: McDonald's Privacy Officer), PO Box 392 Pennant Hills NSW 2120 Australia.
|
| 46 |
+
We may use tracking technologies to collect personal information about you when you use and access a Website or App, including cookies, internet tags or web beacons, and navigational data collection (e.g. log files, server logs, and clickstream data). For example, we may collect information about the date, time and duration of visits and which pages of a Website or App are most commonly accessed. This browsing information is generally not linked to your identity, except where you access a Website or App via links in a message we have sent or where we are able to identify the device or user accessing a Website or App.
|
| 47 |
+
We may combine your anonymous information, browsing information or other information collected through tracking technologies with your personal information collected via our Collection Channels in order to understand and remember your preferences and interests. By accessing a Website or App via links and/or by accessing a Website or App where you have identified yourself, you consent to the collection of this information.
|
| 48 |
+
McDonald's shares personal information with the global McDonald’s Family and our service providers for the purposes described in this privacy policy.
|
| 49 |
+
McDonald’s recognises the trust with which you provide personal information, and except as stated in this privacy policy or any particular Privacy Collection Statement, your information will not be used or disclosed for any other purposes without your consent. However, McDonald's reserves the right to use or disclose any information, including personal information, as needed to satisfy any law, regulation or legal request, to protect the rights or property of McDonald's, any member of the McDonald's Family, or any member of the public, to protect the integrity of a Website or App, to fulfil your requests, or to cooperate in any law enforcement investigation or an investigation on a matter of public safety.
|
| 50 |
+
McDonald’s provides areas on Websites, Apps and various social media platforms where you can upload user-generated content, post or provide information about yourself, communicate with other users, provide reviews for content, products and/or services or interact with or vote on particular content. This information may be publicly posted on a Website, App or social media platforms and/or shared with others, including social media platforms and other public forums in which you choose to participate. This information may become publicly available and may be read, collected and used by others outside of a McDonald’s Website or App. McDonald’s is not responsible for the conduct of others who may read, collect and use this information.
|
| 51 |
+
In some cases, McDonald’s may disclose your personal information to overseas recipients, including but not limited to recipients in the United States of America, Japan, Malaysia and Singapore.
|
| 52 |
+
Your personal information may be stored in different locations depending upon the reason for which you originally submitted the information. If you make an inquiry in relation to your personal information, the more information you can provide us about when you originally submitted your personal information, the quicker McDonald's will be able to retrieve your personal information. McDonald’s may require you to verify your identity by asking you to provide certain information about yourself and provide us with a declaration witnessed and signed by a Justice of Peace. Once your identity is verified, we will work to provide you with your requested information.
|
| 53 |
+
If you request, we will take all reasonable steps to delete your personal information, except where it is required for legal and compliance reasons. Deletion of information may result in McDonald's being unable to facilitate or provide you with information about certain transactions (including the uploading of, access to, and receipt of, content on a Website or App, and purchase transactions undertaken on a Website or App), other content, services or product information, upcoming promotions, competitions or event information, and/or provide certain content, products or services.
|
| 54 |
+
All Websites and Apps operated by McDonald's in Australia will adhere to this privacy policy. The policies on the Websites and Apps of some other members of the McDonald's Family may vary because of local customs, practices or laws.
|
| 55 |
+
Many McDonald's restaurants are owned and operated by independent franchisees. Some franchisees also operate websites and are required to follow this privacy policy.
|
| 56 |
+
If you are concerned that there may have been a breach of this privacy policy by a franchisee, please contact the relevant franchisee entity or McDonald’s restaurant directly.
|
| 57 |
+
If McDonald’s merges with, is acquired by another company, or sells all or a portion of its assets, your personal information may be disclosed to our advisers and any prospective purchaser’s adviser and may be among the assets transferred. However, your personal information will always remain subject to this privacy policy.
|
| 58 |
+
Mail: McDonald's Privacy Officer.
|
| 59 |
+
McDonald's Australia Limited.
|
| 60 |
+
PO Box 392
|
| 61 |
+
Pennant Hills NSW 2120
|
| 62 |
+
Australia.
|
| 63 |
+
Email: privacy@au.mcd.com.
|
| 64 |
+
Telephone: (02) 9875 6666
|
| 65 |
+
Fax: (02) 98756568
|
| 66 |
+
Please allow 14 days for this request to be processed. If you do not receive a satisfactory response from McDonald’s to your query, problem or complaint within 30 calendar days, you may refer your query, problem or complaint to the Office of the Australian Information Commissioner via the contact details listed at https://www.oaic.gov.au/about-us/contact-us/.
|
| 67 |
+
Apple and the Apple logo are trade marks of Apple Inc., registered in the U.S. and other countries. App Store is a service mark of Apple Inc., registered in the U.S. and other countries. Google Play and the Google Play logo are trade marks of Google LLC.
|
| 68 |
+
McDonald’s Australia acknowledges the Aboriginal and Torres Strait Islander peoples as the first inhabitants and the Traditional Custodians of the lands where we live, learn and work.
|
| 69 |
+
McDonald’s collects personal information about you in a number of ways, including when you: use our mobile and tablet apps, including the MyMacca’s app (“Apps”); and.
|
| 70 |
+
McDonald’s collects personal information about you in a number of ways, including when you: interact with us and provide personal information by any other means, including either physically or electronically; and.
|
| 71 |
+
McDonald’s collects personal information about you in a number of ways, including when you: are present at or outside our restaurants, including images, video and audio from CCTV, other cameras (including body cameras), and other security and recording systems.
|
| 72 |
+
When you use one of our Websites or Apps, we may also collect personal information about you in the following general categories: Location information: If you permit an App to access location services in your settings, then we collect your device location to deliver your order or to send you alerts.
|
| 73 |
+
When you use one of our Websites or Apps, we may also collect personal information about you in the following general categories: Transaction information: We collect your transaction details when you place an order via a Website or App, including the products you have ordered, the date and time of your order, the amount charged and your loyalty entitlements.
|
| 74 |
+
When you use one of our Websites or Apps, we may also collect personal information about you in the following general categories: Usage and preferences: We collect information about how you interact with our Websites or Apps, including the pages you visit, your preferences and the settings that you choose. We do this through cookies and other similar technology.
|
| 75 |
+
When you use one of our Websites or Apps, we may also collect personal information about you in the following general categories: Device information: We collect information about your device, such as the hardware model, operating system, preferred language, unique device identifier and mobile network.
|
| 76 |
+
When you use one of our Websites or Apps, we may also collect personal information about you in the following general categories: Other information: We also collect and log information such as your IP address, access dates and times, browser type and pages visited when you interact with a Website or App.
|
| 77 |
+
We also collect personal information about you from third parties, including when: you choose to create an account or register for a product or service via a Website or App using a social media platform (e.g. Facebook, Instagram).
|
| 78 |
+
McDonald’s may collect your personal information via our Collection Channels when you: purchase a product or make a booking through a Website or App.
|
| 79 |
+
McDonald’s may collect your personal information via our Collection Channels when you: participate in any offers, marketing activities (including competitions), loyalty or rewards program or promotional activities.
|
| 80 |
+
McDonald’s may collect your personal information via our Collection Channels when you: contact us or provide us with personal information directly via any medium including a Website or App, SMS or other message service and email, social media platforms, mail, telephone or in person.
|
| 81 |
+
McDonald’s may collect your personal information via our Collection Channels when you: interact with a Website or App for a specific purpose.
|
| 82 |
+
McDonald’s may collect your personal information via our Collection Channels when you: browse a Website or App generally.
|
| 83 |
+
McDonald’s may collect your personal information via our Collection Channels when you: sign-up to, or register an account via any Collection Channel.
|
| 84 |
+
McDonald’s may collect your personal information via our Collection Channels when you: are present at or outside a McDonald’s restaurant and are captured via our security and recording systems (including in car parks, drive thru areas, restaurant entrances or exits and publicly accessible areas); or.
|
| 85 |
+
McDonald’s may collect your personal information via our Collection Channels when you: apply for employment with McDonald’s.
|
| 86 |
+
We collect, hold, use and disclose your personal information for our primary purposes, including: for the purposes stated on a particular Collection Channel or Privacy Collection Statement.
|
| 87 |
+
We collect, hold, use and disclose your personal information for our primary purposes, including: to maintain and improve the functionality of a Website or App.
|
| 88 |
+
We collect, hold, use and disclose your personal information for our primary purposes, including: to manage your orders or facilitate payment, for example, when you use our App the drive thru screen and kiosk will display your name and crew members will greet you by name.
|
| 89 |
+
We collect, hold, use and disclose your personal information for our primary purposes, including: in the case of images and video/audio from our security and recording systems used in and around our restaurants, for security, safety, compliance, and operational purposes.
|
| 90 |
+
We collect, hold, use and disclose your personal information for our primary purposes, including: to provide you with information about your transactions and loyalty entitlements.
|
| 91 |
+
We collect, hold, use and disclose your personal information for our primary purposes, including: to provide marketing materials and information about our products and services, events, special offers, competitions and/or promotions, or to request your feedback for promotional purposes.
|
| 92 |
+
We collect, hold, use and disclose your personal information for our primary purposes, including: to respond to customer enquiries or complaints.
|
| 93 |
+
We collect, hold, use and disclose your personal information for our primary purposes, including: to manage your employment or process your application for employment with McDonald’s (including McDonald’s franchisees), to provide employee assistance programs and facilitate effective employment practices.
|
| 94 |
+
We collect, hold, use and disclose your personal information for our primary purposes, including: to obtain opinions or comments about products and/or services and to conduct other market research and development (including to record statistical data for marketing analysis).
|
| 95 |
+
We collect, hold, use and disclose your personal information for our primary purposes, including: to enter you into and administer promotions/competitions.
|
| 96 |
+
We collect, hold, use and disclose your personal information for our primary purposes, including: to provide, maintain and improve our products and services.
|
| 97 |
+
We collect, hold, use and disclose your personal information for our primary purposes, including: to customise a Website or App based on your preferences.
|
| 98 |
+
We collect, hold, use and disclose your personal information for our primary purposes, including: to allow you to use a Website or App.
|
| 99 |
+
We collect, hold, use and disclose your personal information for our primary purposes, including: to share with your social media communities, to the extent allowed by you.
|
SEM/txt/1/protect_information.txt
CHANGED
|
@@ -1,2 +1,4 @@
|
|
| 1 |
McDonald’s will endeavour to take all reasonable technical, organisation and physical steps to protect your personal information. This includes utilisation of online systems with password protection, secure servers using encryption technology and secure servers that are protected in controlled facilities.
|
| 2 |
All McDonald's employees and service providers are obliged to respect the confidentiality and security of any personal information held by McDonald's. However, McDonald’s cannot guarantee the security of your personal information and will not be held responsible for events arising from unauthorised access to personal information beyond McDonald's reasonable control.
|
|
|
|
|
|
|
|
|
| 1 |
McDonald’s will endeavour to take all reasonable technical, organisation and physical steps to protect your personal information. This includes utilisation of online systems with password protection, secure servers using encryption technology and secure servers that are protected in controlled facilities.
|
| 2 |
All McDonald's employees and service providers are obliged to respect the confidentiality and security of any personal information held by McDonald's. However, McDonald’s cannot guarantee the security of your personal information and will not be held responsible for events arising from unauthorised access to personal information beyond McDonald's reasonable control.
|
| 3 |
+
McDonald’s will endeavour to take all reasonable technical, organisation and physical steps to protect your personal information. This includes utilisation of online systems with password protection, secure servers using encryption technology and secure servers that are protected in controlled facilities.
|
| 4 |
+
All McDonald's employees and service providers are obliged to respect the confidentiality and security of any personal information held by McDonald's. However, McDonald’s cannot guarantee the security of your personal information and will not be held responsible for events arising from unauthorised access to personal information beyond McDonald's reasonable control.
|
SEM/txt/1/share_information.txt
CHANGED
|
@@ -1,3 +1,10 @@
|
|
| 1 |
McDonald's shares personal information with the global McDonald’s Family and our service providers for the purposes described in this privacy policy.
|
| 2 |
McDonald’s recognises the trust with which you provide personal information, and except as stated in this privacy policy or any particular Privacy Collection Statement, your information will not be used or disclosed for any other purposes without your consent. However, McDonald's reserves the right to use or disclose any information, including personal information, as needed to satisfy any law, regulation or legal request, to protect the rights or property of McDonald's, any member of the McDonald's Family, or any member of the public, to protect the integrity of a Website or App, to fulfil your requests, or to cooperate in any law enforcement investigation or an investigation on a matter of public safety.
|
| 3 |
In some cases, McDonald’s may disclose your personal information to overseas recipients, including but not limited to recipients in the United States of America, Japan, Malaysia and Singapore.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
McDonald's shares personal information with the global McDonald’s Family and our service providers for the purposes described in this privacy policy.
|
| 2 |
McDonald’s recognises the trust with which you provide personal information, and except as stated in this privacy policy or any particular Privacy Collection Statement, your information will not be used or disclosed for any other purposes without your consent. However, McDonald's reserves the right to use or disclose any information, including personal information, as needed to satisfy any law, regulation or legal request, to protect the rights or property of McDonald's, any member of the McDonald's Family, or any member of the public, to protect the integrity of a Website or App, to fulfil your requests, or to cooperate in any law enforcement investigation or an investigation on a matter of public safety.
|
| 3 |
In some cases, McDonald’s may disclose your personal information to overseas recipients, including but not limited to recipients in the United States of America, Japan, Malaysia and Singapore.
|
| 4 |
+
We may still send you transaction and administrative information.
|
| 5 |
+
We are not responsible for removing your personal information from the lists of any third party who has previously been provided your information in accordance with this privacy policy.
|
| 6 |
+
We also collect personal information about you from third parties, including when: you have consented to a third party disclosing your personal information to us (e.g. when you enter a competition or promotion run by a third party for us); and.
|
| 7 |
+
We also collect personal information about you from third parties, including when: it is otherwise lawful for a third party to disclose your personal information to us.
|
| 8 |
+
We collect, hold, use and disclose your personal information for our primary purposes, including: to fulfil obligations in respect of any sale and purchase contract and/or any other contract between you and McDonald’s.
|
| 9 |
+
We collect, hold, use and disclose your personal information for our primary purposes, including: to send you any technical, administrative or legal notices important to our Websites and Apps.
|
| 10 |
+
We collect, hold, use and disclose your personal information for our primary purposes, including: to share with trusted third parties including professional service providers, our related bodies corporate, our franchisees, our suppliers and our promotional partners and other trusted third parties (and their directors, servants and agents) and agencies (McDonald’s Family); and.
|
SEM/txt/1/thrid_party.txt
CHANGED
|
@@ -4,3 +4,6 @@ All Websites and Apps operated by McDonald's in Australia will adhere to this pr
|
|
| 4 |
Many McDonald's restaurants are owned and operated by independent franchisees. Some franchisees also operate websites and are required to follow this privacy policy.
|
| 5 |
McDonald’s do not control the use or disclosure of personal information and may not have access to the personal information held by McDonald’s franchisees. McDonald’s franchisees are each independently responsible for ensuring that your personal information collected by them is handled in accordance with this Privacy Policy and the Australian Privacy Principles.
|
| 6 |
If you are concerned that there may have been a breach of this privacy policy by a franchisee, please contact the relevant franchisee entity or McDonald’s restaurant directly.
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
Many McDonald's restaurants are owned and operated by independent franchisees. Some franchisees also operate websites and are required to follow this privacy policy.
|
| 5 |
McDonald’s do not control the use or disclosure of personal information and may not have access to the personal information held by McDonald’s franchisees. McDonald’s franchisees are each independently responsible for ensuring that your personal information collected by them is handled in accordance with this Privacy Policy and the Australian Privacy Principles.
|
| 6 |
If you are concerned that there may have been a breach of this privacy policy by a franchisee, please contact the relevant franchisee entity or McDonald’s restaurant directly.
|
| 7 |
+
Our Websites or Apps contain links to sites operated by third parties. We are not responsible for the privacy practices of, or any content on, those sites linked to our Websites and Apps. If you visit one of these linked websites, we encourage you to review their privacy and other policies.
|
| 8 |
+
We may use third party advertisements on our Websites and Apps. All third party advertising, if paid for, is paid for by the relevant third party advertisers. Third party advertisements are not recommendations or endorsements by McDonald’s or any of its affiliates. To the extent permitted by law, McDonald’s is not responsible for the content (including representations) of any third party advertisement on a Website or App. Cookies may be associated with these advertisements to enable the advertiser to track the number of anonymous users responding to the campaign.
|
| 9 |
+
McDonald’s collects personal information about you in a number of ways, including when you: use our websites (including mcdonalds.com.au), social media pages, and internal websites or intranet (“Website”).
|
SEM/txt/1/update.txt
CHANGED
|
@@ -1,2 +1,3 @@
|
|
| 1 |
From time to time, it may be necessary for McDonald's to change this privacy policy without notice. We will post any changes to this privacy policy on our Websites and Apps. Rest assured, however, that any changes will not be retroactively applied and will not alter how we handle previously collected personal information.
|
| 2 |
If McDonald’s merges with, is acquired by another company, or sells all or a portion of its assets, your personal information may be disclosed to our advisers and any prospective purchaser’s adviser and may be among the assets transferred. However, your personal information will always remain subject to this privacy policy.
|
|
|
|
|
|
| 1 |
From time to time, it may be necessary for McDonald's to change this privacy policy without notice. We will post any changes to this privacy policy on our Websites and Apps. Rest assured, however, that any changes will not be retroactively applied and will not alter how we handle previously collected personal information.
|
| 2 |
If McDonald’s merges with, is acquired by another company, or sells all or a portion of its assets, your personal information may be disclosed to our advisers and any prospective purchaser’s adviser and may be among the assets transferred. However, your personal information will always remain subject to this privacy policy.
|
| 3 |
+
From time to time, it may be necessary for McDonald's to change this privacy policy without notice. We will post any changes to this privacy policy on our Websites and Apps. Rest assured, however, that any changes will not be retroactively applied and will not alter how we handle previously collected personal information.
|
SEM/txt/1/user_right.txt
CHANGED
|
@@ -1 +1,8 @@
|
|
| 1 |
McDonald’s provides areas on Websites, Apps and various social media platforms where you can upload user-generated content, post or provide information about yourself, communicate with other users, provide reviews for content, products and/or services or interact with or vote on particular content. This information may be publicly posted on a Website, App or social media platforms and/or shared with others, including social media platforms and other public forums in which you choose to participate. This information may become publicly available and may be read, collected and used by others outside of a McDonald’s Website or App. McDonald’s is not responsible for the conduct of others who may read, collect and use this information.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
McDonald’s provides areas on Websites, Apps and various social media platforms where you can upload user-generated content, post or provide information about yourself, communicate with other users, provide reviews for content, products and/or services or interact with or vote on particular content. This information may be publicly posted on a Website, App or social media platforms and/or shared with others, including social media platforms and other public forums in which you choose to participate. This information may become publicly available and may be read, collected and used by others outside of a McDonald’s Website or App. McDonald’s is not responsible for the conduct of others who may read, collect and use this information.
|
| 2 |
+
You don’t have to provide any personal information to us. However, if you do not do so, this may affect or completely restrict your ability to use our products and services, including our Websites or App, our ability to provide you with relevant content, prizes, products and services, or our ability to process your queries and employment applications.
|
| 3 |
+
If you would like to opt out of receiving advertising communications from us, the McDonald’s Family and our trusted third parties, you can unsubscribe.
|
| 4 |
+
If you no longer wish to receive any communications from McDonald’s via an App, you can delete the App from your device.
|
| 5 |
+
You are in control of any personal information you provide to us. If, at any time, you would like to access, review, correct and/or delete the personal information we have about you, or if you would like to change your contact preferences, you can let us know via the contact details listed below. Please allow 30 days for this request to be processed.
|
| 6 |
+
McDonald’s do not control the use or disclosure of personal information and may not have access to the personal information held by McDonald’s franchisees. McDonald’s franchisees are each independently responsible for ensuring that your personal information collected by them is handled in accordance with this Privacy Policy and the Australian Privacy Principles.
|
| 7 |
+
If you have any questions about our privacy policy, or any problems or complaints about how we have collected, used, stored, handled and/or disclosed your personal information, please contact us at.
|
| 8 |
+
When you use one of our Websites or Apps, we may also collect personal information about you in the following general categories: Employee information: If you are a job applicant, an employee in one of our restaurants or our corporate offices, or a former employee, and use a Website or App, we collect information about the training modules you have completed, the forms you have submitted, personal information you have provided, the approvals you have given or received, and other similar information related to your job.
|
app.py
CHANGED
|
@@ -26,6 +26,12 @@ from google.oauth2 import service_account
|
|
| 26 |
from googleapiclient.discovery import build
|
| 27 |
from googleapiclient.http import MediaFileUpload
|
| 28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
title = "Cpp4App_test"
|
| 30 |
description = "Automated Contextual Privacy Policies Generation for Mobile Apps"
|
| 31 |
|
|
@@ -149,21 +155,27 @@ def write_and_read():
|
|
| 149 |
with open('myfile.txt', 'r') as f:
|
| 150 |
data = f.read()
|
| 151 |
|
| 152 |
-
print("this is data: ", data)
|
| 153 |
|
| 154 |
return data
|
| 155 |
|
| 156 |
def run_demo(img_root, output_root, segment_root, file):
|
| 157 |
-
print(type(file))
|
| 158 |
|
| 159 |
# file_content = file.read().decode('utf-8')
|
| 160 |
run_single_pp(file)
|
| 161 |
|
| 162 |
-
|
| 163 |
|
| 164 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
| 165 |
|
| 166 |
def inference(img, html):
|
|
|
|
|
|
|
| 167 |
|
| 168 |
write_and_read()
|
| 169 |
|
|
@@ -195,31 +207,65 @@ def inference(img, html):
|
|
| 195 |
# with open(pp_root, 'w', encoding='utf-8') as file: # Open the destination file in text mode
|
| 196 |
# file.write(html) # Write the HTML content to the destination file
|
| 197 |
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 205 |
with open(pp_root, 'w', encoding='utf-8') as file:
|
| 206 |
file.write(input_text)
|
| 207 |
|
| 208 |
soup = BeautifulSoup(open(pp_root, encoding='utf-8'), features="html.parser")
|
| 209 |
# print("pp_root soup: ", soup.contents)
|
| 210 |
|
| 211 |
-
|
| 212 |
-
|
| 213 |
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
|
| 220 |
# print(output_data)
|
| 221 |
|
| 222 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 223 |
|
| 224 |
# inputs = [
|
| 225 |
# gr.inputs.Image(type="pil", label="Image Upload"),
|
|
@@ -325,7 +371,7 @@ def new_example_inference_3():
|
|
| 325 |
# def toggle_dataframe_callback():
|
| 326 |
# complete_result_dataframe.visible = not complete_result_dataframe.visible
|
| 327 |
|
| 328 |
-
with gr.Blocks(css=
|
| 329 |
button[class*="btn"] {
|
| 330 |
all: unset; /* 移除所有样式 */
|
| 331 |
display: inline-block; /* 确保按钮仍然是块元素 */
|
|
@@ -339,55 +385,31 @@ with gr.Blocks(css="""
|
|
| 339 |
border-radius: 5px !important;
|
| 340 |
text-align: center;
|
| 341 |
}
|
| 342 |
-
|
| 343 |
.icon-buttons {
|
| 344 |
display: none;
|
| 345 |
}
|
| 346 |
-
|
| 347 |
-
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
.title {
|
| 352 |
-
font-size: 80px !important;
|
| 353 |
-
font-weight: bolder;
|
| 354 |
-
margin-top: 50px;
|
| 355 |
-
}
|
| 356 |
-
|
| 357 |
-
.title_msg1 {
|
| 358 |
-
font-size: 60px !important;
|
| 359 |
-
margin-top: 10px;
|
| 360 |
-
font-weight: bolder;
|
| 361 |
-
}
|
| 362 |
-
|
| 363 |
-
.title_msg2 {
|
| 364 |
-
font-weight: bolder;
|
| 365 |
-
}
|
| 366 |
-
|
| 367 |
-
.title_img img {
|
| 368 |
-
border-radius: 0px !important;
|
| 369 |
-
cursor: default;
|
| 370 |
-
}
|
| 371 |
-
|
| 372 |
-
.title_img {
|
| 373 |
-
border-radius: 0px !important;
|
| 374 |
}
|
| 375 |
|
| 376 |
-
|
| 377 |
-
|
| 378 |
-
font-weight: bolder;
|
| 379 |
-
margin-top: 120px !important;
|
| 380 |
}
|
| 381 |
-
|
| 382 |
-
.
|
| 383 |
-
|
| 384 |
-
|
| 385 |
-
|
| 386 |
-
|
|
|
|
| 387 |
}
|
| 388 |
-
|
| 389 |
.eg_img {
|
| 390 |
-
width:
|
| 391 |
padding: 0;
|
| 392 |
display: block;
|
| 393 |
margin: 0 auto; /* 图片居中 */
|
|
@@ -396,54 +418,43 @@ with gr.Blocks(css="""
|
|
| 396 |
background-size: cover !important;
|
| 397 |
background-position: center !important;
|
| 398 |
background-repeat: no-repeat !important;
|
| 399 |
-
padding-bottom:
|
| 400 |
}
|
| 401 |
-
|
| 402 |
.eg_img:hover {
|
| 403 |
border-color: rgb(117, 209, 255) !important; /* 悬停时边框颜色 */
|
| 404 |
border-width: 2px !important; /* 悬停时边框粗细 */
|
| 405 |
}
|
| 406 |
-
|
| 407 |
.eg1 {
|
| 408 |
background-image: url('https://buyanghc.github.io/eg1.jpg') !important;
|
| 409 |
}
|
| 410 |
-
|
| 411 |
.eg2 {
|
| 412 |
background-image: url('https://buyanghc.github.io/eg2.jpg') !important;
|
| 413 |
}
|
| 414 |
-
|
| 415 |
.eg3 {
|
| 416 |
background-image: url('https://buyanghc.github.io/eg3.jpg') !important;
|
| 417 |
}
|
| 418 |
-
|
| 419 |
.eg_img_msg {
|
| 420 |
text-align: center; /* 文本居中 */
|
| 421 |
-
margin-top: 10px;
|
| 422 |
}
|
| 423 |
|
| 424 |
-
.
|
| 425 |
-
|
| 426 |
-
gap: 60px; /* 调整列之间的间距 */
|
| 427 |
-
margin-bottom: 120px;
|
| 428 |
-
width: 100%;
|
| 429 |
-
}
|
| 430 |
-
|
| 431 |
-
.col {
|
| 432 |
-
height: 100%;
|
| 433 |
-
}
|
| 434 |
-
|
| 435 |
-
.work_title h1{
|
| 436 |
-
font-size: 50px !important;
|
| 437 |
-
font-weight: bolder;
|
| 438 |
-
text-align: left;
|
| 439 |
}
|
| 440 |
|
| 441 |
.btn-container {
|
|
|
|
| 442 |
display: flex;
|
| 443 |
-
justify-content:
|
| 444 |
gap: 45px; /* 按钮之间的间距 */
|
|
|
|
|
|
|
| 445 |
}
|
| 446 |
-
|
| 447 |
.btn {
|
| 448 |
width: 150px;
|
| 449 |
height: 45px;
|
|
@@ -451,110 +462,96 @@ with gr.Blocks(css="""
|
|
| 451 |
transition: border-color 0.3s ease, color 0.3s ease, background-color 0.3s ease !important;
|
| 452 |
border-radius: 5px;
|
| 453 |
}
|
| 454 |
-
|
| 455 |
.btn_run {
|
| 456 |
color: white !important;
|
| 457 |
background-color: rgb(40, 40, 40) !important;
|
| 458 |
}
|
| 459 |
-
|
| 460 |
.btn_reset {
|
| 461 |
background-color: rgb(234, 234, 234) !important;
|
| 462 |
}
|
| 463 |
-
|
| 464 |
.btn:hover{
|
| 465 |
color: white !important;
|
| 466 |
background-color: rgb(117, 209, 255) !important;
|
| 467 |
border: white !important;
|
| 468 |
}
|
| 469 |
|
| 470 |
-
.
|
| 471 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 472 |
}
|
| 473 |
|
| 474 |
-
.
|
| 475 |
-
|
| 476 |
-
margin-bottom: 300px;
|
| 477 |
display: flex;
|
| 478 |
-
justify-content:
|
| 479 |
-
|
| 480 |
-
}
|
| 481 |
-
|
| 482 |
-
.work_msg{
|
| 483 |
-
margin-bottom: 10px;
|
| 484 |
-
}
|
| 485 |
-
|
| 486 |
-
.image_show{
|
| 487 |
-
width: 100%;
|
| 488 |
-
height: calc(100vw * 0.6);
|
| 489 |
-
}
|
| 490 |
-
|
| 491 |
-
.point{
|
| 492 |
-
all: unset;
|
| 493 |
-
width: 50%;
|
| 494 |
-
height: auto;
|
| 495 |
-
border-radius: 0px !important;
|
| 496 |
-
cursor: default !important;
|
| 497 |
-
border: none !important;
|
| 498 |
}
|
| 499 |
-
|
| 500 |
-
""") as demo:
|
| 501 |
|
| 502 |
-
|
| 503 |
-
with gr.Row():
|
| 504 |
-
with gr.Column(scale=1):
|
| 505 |
-
gr.Markdown("<h1 style='font-size: 80px; font-weight: border;'>Cpp4App</h1>", elem_classes="title")
|
| 506 |
-
gr.Markdown("<h2>Automated Contextual Privacy Policies Generation </h2>", elem_classes="title_msg1")
|
| 507 |
-
gr.Markdown("<h2>for Mobile Apps.</h2>",elem_classes="title_msg2")
|
| 508 |
|
|
|
|
| 509 |
with gr.Column(scale=1):
|
| 510 |
-
gr.
|
| 511 |
-
|
| 512 |
-
|
| 513 |
-
gr.Markdown("<h1 style='font-size: 80px; font-weight: border;'>· EXAMPLES</h1>", elem_classes="eg_title")
|
| 514 |
-
gr.Markdown("<h2>Click to run the example !</h2>", elem_classes="eg_msg")
|
| 515 |
-
|
| 516 |
-
with gr.Row(elem_classes="example_imgs"):
|
| 517 |
-
with gr.Column(scale=1, elem_classes="col"):
|
| 518 |
-
eg1_img = gr.Button("", elem_classes="eg_img eg1")
|
| 519 |
-
gr.Markdown("<h2>· WhatsApp</h2>", elem_classes="eg_img_msg")
|
| 520 |
-
|
| 521 |
-
with gr.Column(scale=1, elem_classes="col"):
|
| 522 |
-
eg2_img = gr.Button("", elem_classes="eg_img eg2")
|
| 523 |
-
gr.Markdown("<h2>· Snap</h2>", elem_classes="eg_img_msg")
|
| 524 |
|
| 525 |
-
with gr.Column(scale=1
|
| 526 |
-
|
| 527 |
-
gr.Markdown("<h2>· Mcdonald's</h2>", elem_classes="eg_img_msg")
|
| 528 |
|
| 529 |
-
with gr.Row(elem_classes="work_head"):
|
| 530 |
-
with gr.Column(scale=8):
|
| 531 |
-
gr.Markdown("<h1 style='font-size: 80px; font-weight: bold;'>· WORKSPACE</h1>", elem_classes="work_title")
|
| 532 |
|
| 533 |
-
|
| 534 |
-
|
| 535 |
-
|
| 536 |
-
reset_btn = gr.Button("RESET", elem_classes="btn btn_reset")
|
| 537 |
|
| 538 |
with gr.Column():
|
| 539 |
-
gr.Markdown("<h2>Step 1 : Input privacy policy URL</h2>", elem_classes="work_msg")
|
| 540 |
-
text_input = gr.Textbox(label="URL Input for the Privacy Policy of the App", elem_classes="url")
|
| 541 |
|
| 542 |
with gr.Row(elem_classes="work2"):
|
| 543 |
-
with gr.Column(scale=
|
| 544 |
-
gr.Markdown("<
|
|
|
|
|
|
|
|
|
|
| 545 |
image_input = gr.Image(type="pil", label="Screenshot Upload", elem_classes="image_show")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 546 |
|
| 547 |
-
|
| 548 |
-
|
|
|
|
| 549 |
|
| 550 |
-
|
| 551 |
-
|
| 552 |
-
|
|
|
|
| 553 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 554 |
|
| 555 |
|
| 556 |
run_btn.click(inference, inputs=[image_input, text_input], outputs=[result_image])
|
| 557 |
reset_btn.click(lambda: [None, None, None, None, None, None], inputs=[], outputs=[image_input, text_input, result_image])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 558 |
# example_button.click(example_inference, inputs=[], outputs=[image_input, text_input, result_image, result_dataframe])
|
| 559 |
eg1_img.click(new_example_inference_1,
|
| 560 |
inputs=[],
|
|
|
|
| 26 |
from googleapiclient.discovery import build
|
| 27 |
from googleapiclient.http import MediaFileUpload
|
| 28 |
|
| 29 |
+
from dotenv import load_dotenv
|
| 30 |
+
import os
|
| 31 |
+
|
| 32 |
+
# 加载 .env 文件中的环境变量
|
| 33 |
+
load_dotenv()
|
| 34 |
+
|
| 35 |
title = "Cpp4App_test"
|
| 36 |
description = "Automated Contextual Privacy Policies Generation for Mobile Apps"
|
| 37 |
|
|
|
|
| 155 |
with open('myfile.txt', 'r') as f:
|
| 156 |
data = f.read()
|
| 157 |
|
| 158 |
+
# print("this is data: ", data)
|
| 159 |
|
| 160 |
return data
|
| 161 |
|
| 162 |
def run_demo(img_root, output_root, segment_root, file):
|
| 163 |
+
# print(type(file))
|
| 164 |
|
| 165 |
# file_content = file.read().decode('utf-8')
|
| 166 |
run_single_pp(file)
|
| 167 |
|
| 168 |
+
output_boards = run_single_img(img_root, output_root, segment_root)
|
| 169 |
|
| 170 |
+
return output_boards
|
| 171 |
+
|
| 172 |
+
# 定义全局变量存储图集和当前显示的图片索引
|
| 173 |
+
image_list = []
|
| 174 |
+
current_image_index = 0
|
| 175 |
|
| 176 |
def inference(img, html):
|
| 177 |
+
start = time.process_time()
|
| 178 |
+
global output_boards, current_image_index # 让output_boards成为全局变量
|
| 179 |
|
| 180 |
write_and_read()
|
| 181 |
|
|
|
|
| 207 |
# with open(pp_root, 'w', encoding='utf-8') as file: # Open the destination file in text mode
|
| 208 |
# file.write(html) # Write the HTML content to the destination file
|
| 209 |
|
| 210 |
+
# 使用网址命名html文件
|
| 211 |
+
html_folder = "./html_files"
|
| 212 |
+
if not os.path.exists(html_folder):
|
| 213 |
+
os.makedirs(html_folder)
|
| 214 |
+
|
| 215 |
+
# 使用网址创建合法的文件名
|
| 216 |
+
html_filename = os.path.join(html_folder, html.replace("://", "_").replace("/", "_") + ".html")
|
| 217 |
+
|
| 218 |
+
# 如果html文件不存在则下载并保存
|
| 219 |
+
if not os.path.exists(html_filename):
|
| 220 |
+
try:
|
| 221 |
+
response = requests.get(html)
|
| 222 |
+
response.raise_for_status() # Will raise an exception if the status is an error
|
| 223 |
+
input_text = response.text
|
| 224 |
+
# 将HTML内容保存到文件
|
| 225 |
+
with open(html_filename, 'w', encoding='utf-8') as file:
|
| 226 |
+
file.write(input_text)
|
| 227 |
+
except requests.HTTPError:
|
| 228 |
+
input_text = ""
|
| 229 |
+
else:
|
| 230 |
+
# 如果文件存在,则直接读取
|
| 231 |
+
with open(html_filename, 'r', encoding='utf-8') as file:
|
| 232 |
+
input_text = file.read()
|
| 233 |
+
|
| 234 |
with open(pp_root, 'w', encoding='utf-8') as file:
|
| 235 |
file.write(input_text)
|
| 236 |
|
| 237 |
soup = BeautifulSoup(open(pp_root, encoding='utf-8'), features="html.parser")
|
| 238 |
# print("pp_root soup: ", soup.contents)
|
| 239 |
|
| 240 |
+
output_boards = run_demo(img_root, output_root, segment_root, pp_root)
|
|
|
|
| 241 |
|
| 242 |
+
for i in range(len(output_boards)):
|
| 243 |
+
# 确保 output_board 是图像对象
|
| 244 |
+
if isinstance(output_boards[i], tuple):
|
| 245 |
+
# 如果是 tuple,转换为 NumPy 数组或其他图像格式
|
| 246 |
+
output_boards[i] = np.array(output_boards[i])
|
| 247 |
|
| 248 |
# print(output_data)
|
| 249 |
|
| 250 |
+
current_image_index = 0 # 每次运行inference后重置图片索引
|
| 251 |
+
|
| 252 |
+
total = time.process_time() - start
|
| 253 |
+
print(f"total processing time of this screenshot: {total:.2f}s")
|
| 254 |
+
return output_boards[current_image_index] # 返回图集中的第一张图像
|
| 255 |
+
|
| 256 |
+
# 向左切换图片
|
| 257 |
+
def previous_image():
|
| 258 |
+
global current_image_index
|
| 259 |
+
if current_image_index > 0:
|
| 260 |
+
current_image_index -= 1
|
| 261 |
+
return output_boards[current_image_index]
|
| 262 |
+
|
| 263 |
+
# 向右切换图片
|
| 264 |
+
def next_image():
|
| 265 |
+
global current_image_index
|
| 266 |
+
if current_image_index < len(output_boards) - 1:
|
| 267 |
+
current_image_index += 1
|
| 268 |
+
return output_boards[current_image_index]
|
| 269 |
|
| 270 |
# inputs = [
|
| 271 |
# gr.inputs.Image(type="pil", label="Image Upload"),
|
|
|
|
| 371 |
# def toggle_dataframe_callback():
|
| 372 |
# complete_result_dataframe.visible = not complete_result_dataframe.visible
|
| 373 |
|
| 374 |
+
with gr.Blocks(css='''
|
| 375 |
button[class*="btn"] {
|
| 376 |
all: unset; /* 移除所有样式 */
|
| 377 |
display: inline-block; /* 确保按钮仍然是块元素 */
|
|
|
|
| 385 |
border-radius: 5px !important;
|
| 386 |
text-align: center;
|
| 387 |
}
|
| 388 |
+
|
| 389 |
.icon-buttons {
|
| 390 |
display: none;
|
| 391 |
}
|
| 392 |
+
|
| 393 |
+
body {
|
| 394 |
+
display: flex;
|
| 395 |
+
justify-content: center;
|
| 396 |
+
margin: 0; /* 去除默认的 body 外边距 */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 397 |
}
|
| 398 |
|
| 399 |
+
h1, h2{
|
| 400 |
+
width: 100%;
|
|
|
|
|
|
|
| 401 |
}
|
| 402 |
+
|
| 403 |
+
.example_imgs {
|
| 404 |
+
width: 100%;
|
| 405 |
+
display: flex;
|
| 406 |
+
justify-content: flex-start; /* 图片居左对齐 */
|
| 407 |
+
align-items: flex-start; /* 垂直居中对齐 */
|
| 408 |
+
gap: 20px; /* 控制图片之间的间距 */
|
| 409 |
}
|
| 410 |
+
|
| 411 |
.eg_img {
|
| 412 |
+
width: 40%; /* 调整图片大小 */
|
| 413 |
padding: 0;
|
| 414 |
display: block;
|
| 415 |
margin: 0 auto; /* 图片居中 */
|
|
|
|
| 418 |
background-size: cover !important;
|
| 419 |
background-position: center !important;
|
| 420 |
background-repeat: no-repeat !important;
|
| 421 |
+
padding-bottom: 80% !important;
|
| 422 |
}
|
| 423 |
+
|
| 424 |
.eg_img:hover {
|
| 425 |
border-color: rgb(117, 209, 255) !important; /* 悬停时边框颜色 */
|
| 426 |
border-width: 2px !important; /* 悬停时边框粗细 */
|
| 427 |
}
|
| 428 |
+
|
| 429 |
.eg1 {
|
| 430 |
background-image: url('https://buyanghc.github.io/eg1.jpg') !important;
|
| 431 |
}
|
| 432 |
+
|
| 433 |
.eg2 {
|
| 434 |
background-image: url('https://buyanghc.github.io/eg2.jpg') !important;
|
| 435 |
}
|
| 436 |
+
|
| 437 |
.eg3 {
|
| 438 |
background-image: url('https://buyanghc.github.io/eg3.jpg') !important;
|
| 439 |
}
|
| 440 |
+
|
| 441 |
.eg_img_msg {
|
| 442 |
text-align: center; /* 文本居中 */
|
|
|
|
| 443 |
}
|
| 444 |
|
| 445 |
+
.col{
|
| 446 |
+
width: 20% !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 447 |
}
|
| 448 |
|
| 449 |
.btn-container {
|
| 450 |
+
width: 100%
|
| 451 |
display: flex;
|
| 452 |
+
justify-content: center; /* 按钮容器中的内容右对齐 */
|
| 453 |
gap: 45px; /* 按钮之间的间距 */
|
| 454 |
+
margin-top: 15px;
|
| 455 |
+
margin-bottom: 15px;
|
| 456 |
}
|
| 457 |
+
|
| 458 |
.btn {
|
| 459 |
width: 150px;
|
| 460 |
height: 45px;
|
|
|
|
| 462 |
transition: border-color 0.3s ease, color 0.3s ease, background-color 0.3s ease !important;
|
| 463 |
border-radius: 5px;
|
| 464 |
}
|
| 465 |
+
|
| 466 |
.btn_run {
|
| 467 |
color: white !important;
|
| 468 |
background-color: rgb(40, 40, 40) !important;
|
| 469 |
}
|
| 470 |
+
|
| 471 |
.btn_reset {
|
| 472 |
background-color: rgb(234, 234, 234) !important;
|
| 473 |
}
|
| 474 |
+
|
| 475 |
.btn:hover{
|
| 476 |
color: white !important;
|
| 477 |
background-color: rgb(117, 209, 255) !important;
|
| 478 |
border: white !important;
|
| 479 |
}
|
| 480 |
|
| 481 |
+
.change_btn{
|
| 482 |
+
width: 55px !important;
|
| 483 |
+
height: 25px !important;
|
| 484 |
+
border-radius: 50% !important;
|
| 485 |
+
background-color: rgb(234, 234, 234) !important;
|
| 486 |
+
padding: 0 !important;
|
| 487 |
+
margin: 0 !important;
|
| 488 |
}
|
| 489 |
|
| 490 |
+
.btn-container2 {
|
| 491 |
+
width: 40%;
|
|
|
|
| 492 |
display: flex;
|
| 493 |
+
justify-content: flex-end; /* 按钮容器中的内容右对齐 */
|
| 494 |
+
gap: 20px; /* 按钮之间的间距 */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 495 |
}
|
|
|
|
|
|
|
| 496 |
|
| 497 |
+
''') as demo:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 498 |
|
| 499 |
+
with gr.Row():
|
| 500 |
with gr.Column(scale=1):
|
| 501 |
+
gr.Markdown("<h1 style='font-size: 50px; font-weight: border; text-align: center;'>Cpp4App</h1>", elem_classes="title")
|
| 502 |
+
gr.Markdown("<p style='text-align: center;'>Automated Contextual Privacy Policies Generation for Mobile Apps.</p>", elem_classes="title_msg1")
|
| 503 |
+
gr.Markdown("<p style='text-align: center; margin-top: -15px;'>[Usage] Upload the screenshot and privacy policy URL link, then click 'RUN' button.</p>", elem_classes="title_msg1")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 504 |
|
| 505 |
+
# with gr.Column(scale=1):
|
| 506 |
+
# gr.Image("images/head.jpg", elem_classes="title_img img")
|
|
|
|
| 507 |
|
|
|
|
|
|
|
|
|
|
| 508 |
|
| 509 |
+
with gr.Row(elem_classes="btn-container"):
|
| 510 |
+
run_btn = gr.Button("RUN", elem_classes="btn btn_run")
|
| 511 |
+
reset_btn = gr.Button("RESET", elem_classes="btn btn_reset")
|
|
|
|
| 512 |
|
| 513 |
with gr.Column():
|
|
|
|
|
|
|
| 514 |
|
| 515 |
with gr.Row(elem_classes="work2"):
|
| 516 |
+
with gr.Column(elem_classes="col_big", scale=1):
|
| 517 |
+
gr.Markdown("<p style='font-weight: bold; font-size: 18px;'>Step 1 : Input privacy policy URL ⬇️</p>", elem_classes="work_msg")
|
| 518 |
+
text_input = gr.Textbox(label="URL Input for the Privacy Policy of the App", elem_classes="url")
|
| 519 |
+
with gr.Column(elem_classes="col_big", scale=1):
|
| 520 |
+
gr.Markdown("<p style='font-weight: bold; font-size: 18px;'>Step 2 : Upload the screenshot ⬇️</p>", elem_classes="work_msg")
|
| 521 |
image_input = gr.Image(type="pil", label="Screenshot Upload", elem_classes="image_show")
|
| 522 |
+
with gr.Column(elem_classes="col_big", scale=1):
|
| 523 |
+
with gr.Row():
|
| 524 |
+
gr.Markdown("<p style='width: 60%; font-weight: bold; font-size: 18px;'>Output 🌟:</p>", elem_classes="work_msg")
|
| 525 |
+
with gr.Row(elem_classes="btn-container2"):
|
| 526 |
+
previous_button = gr.Button("<", elem_classes="change_btn")
|
| 527 |
+
next_button = gr.Button(">", elem_classes="change_btn")
|
| 528 |
+
result_image = gr.Image(type="pil", label="Result Screenshot", elem_classes="image_show")
|
| 529 |
|
| 530 |
+
with gr.Column():
|
| 531 |
+
gr.Markdown("<h2 style='font-size: 18px; font-weight: border;'>You can try with three examples we provided:</h2>", elem_classes="eg_title")
|
| 532 |
+
gr.Markdown("<p>· Click the picture to run.</p>", elem_classes="eg_msg")
|
| 533 |
|
| 534 |
+
with gr.Row(elem_classes="example_imgs"):
|
| 535 |
+
with gr.Column(elem_classes="col"):
|
| 536 |
+
eg1_img = gr.Button("", elem_classes="eg_img eg1")
|
| 537 |
+
gr.Markdown("<h2 style='font-size: 18px; font-weight: border;'>· WhatsApp</h2>", elem_classes="eg_img_msg")
|
| 538 |
|
| 539 |
+
with gr.Column(elem_classes="col"):
|
| 540 |
+
eg2_img = gr.Button("", elem_classes="eg_img eg2")
|
| 541 |
+
gr.Markdown("<h2 style='font-size: 18px; font-weight: border;'>· Snap</h2>", elem_classes="eg_img_msg")
|
| 542 |
+
|
| 543 |
+
with gr.Column(elem_classes="col"):
|
| 544 |
+
eg3_img = gr.Button("", elem_classes="eg_img eg3")
|
| 545 |
+
gr.Markdown("<h2 style='font-size: 18px; font-weight: border;'>· Mcdonald's</h2>", elem_classes="eg_img_msg")
|
| 546 |
|
| 547 |
|
| 548 |
run_btn.click(inference, inputs=[image_input, text_input], outputs=[result_image])
|
| 549 |
reset_btn.click(lambda: [None, None, None, None, None, None], inputs=[], outputs=[image_input, text_input, result_image])
|
| 550 |
+
|
| 551 |
+
# 点击左右切换按钮时切换显示的图片
|
| 552 |
+
previous_button.click(previous_image, outputs=result_image)
|
| 553 |
+
next_button.click(next_image, outputs=result_image)
|
| 554 |
+
|
| 555 |
# example_button.click(example_inference, inputs=[], outputs=[image_input, text_input, result_image, result_dataframe])
|
| 556 |
eg1_img.click(new_example_inference_1,
|
| 557 |
inputs=[],
|
logs/app.log
CHANGED
|
@@ -1,2 +0,0 @@
|
|
| 1 |
-
2024-08-30 07:10:40 - INFO - Memory usage: 92.3% (Total: 34359738368, Used: 3372806144, Free: 22478848)
|
| 2 |
-
2024-08-30 07:10:40 - INFO - Disk usage: 6.2% (Total: 994662584320, Used: 20487077888, Free: 308522999808)
|
|
|
|
|
|
|
|
|