Skip to content

Commit f09b86b

Browse files
author
Chris Maunder
committed
Initial Commit
0 parents  commit f09b86b

16 files changed

+1088
-0
lines changed

.gitignore

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Misc
2+
.DS_Store
3+
4+
# Python cache
5+
__pycache__/
6+
*.pyc
7+
8+
# debug debris
9+
plate.png
10+
11+
# Generated package files
12+
*-[0-9]*.[0-9]*.[0-9]*.zip
13+
14+
# Models
15+
paddleocr
16+
17+
# Python install / Virtual environment
18+
bin/

README.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Text-to-Image Module for CodeProject.AI Server
2+
3+
This is a Text-to-Image module using the for [CodeProject.AI Server](https://www.codeproject.com/Articles/5322557/CodeProject-AI-Server-AI-the-easy-way). The actual module itself is downloadable via the CodeProject.AI Server's dashboard.
4+
5+
## To develop and debug this code
6+
7+
1. Clone the main [server repo](https://github.com/codeproject/CodeProject.AI-Server) into a directory such as `CodeProject/CodeProject.AI-Server`
8+
9+
2. Clone this Text2Image repo into a separate folder `CodeProject/CodeProject.AI-Modules`
10+
11+
You should now have
12+
13+
```text
14+
CodeProject
15+
- CodeProject.AI-Server
16+
- demos
17+
- src
18+
- ... etc
19+
- CodeProject.AI-Modules
20+
- CodeProject.AI-Text2Image (this repo)
21+
```
22+
23+
3. **If you have NOT run dev setup on the server**
24+
Run the server dev setup scripts by opening a terminal in `CodeProject.AI-Server/src/` then, for Windows, run `setup.bat`, or for Linux/macOS run `bash setup.sh`.<br>
25+
This will setup the server, and will also setup this module as long as this module sits under a folder named `CodeProject.AI-Modules`, with `CodeProject.AI-Modules` being at the same folder level as `CodeProject.AI-Server`.
26+
27+
**If you have already setup the server**
28+
You can run the setup for just this module running the setup script from a terminal opened in this folder
29+
```BAT
30+
REM For Windows
31+
..\..\CodeProject.AI-Server\src\setup.bat
32+
```
33+
```bash
34+
# For Linux/macOS
35+
bash ../../CodeProject.AI-Server/src/setup.sh
36+
```
37+
4. Open the server repo in Visual Studio Code (or Visual Studio) and build and launch the server (Build and Launch server in the Run and Debug menu in VS Code). This will start the server, which in turn will load the settings file from this module.
38+
<br>You can start this module directly from the CodeProject.AI Server dashboard, or you can run this module as a separate process via the 'Launch Text2Image' Debug and Run option in VS Code.
39+
40+
## To create a package for this module
41+
42+
Assuming the folder structure outlined above, run
43+
44+
```BAT
45+
REM For Windows
46+
..\..\CodeProject.AI-Server\src\create_packages.bat
47+
```
48+
```bash
49+
# For Linux/macOS
50+
bash ../../CodeProject.AI-Server/src/create_packages.sh
51+
```

Text2Image.pyproj

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
2+
<PropertyGroup>
3+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
4+
<SchemaVersion>2.0</SchemaVersion>
5+
<ProjectGuid>2022ed32-14c4-4ca6-aac3-d58d724805ed</ProjectGuid>
6+
<ProjectHome>.</ProjectHome>
7+
<StartupFile>stable_diffusion_adapter.py</StartupFile>
8+
<SearchPath>
9+
</SearchPath>
10+
<WorkingDirectory>.</WorkingDirectory>
11+
<OutputPath>.</OutputPath>
12+
<Name>Text2Image</Name>
13+
<RootNamespace>Text2Image</RootNamespace>
14+
<InterpreterId>MSBuild|venv|$(MSBuildProjectFullPath)</InterpreterId>
15+
</PropertyGroup>
16+
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
17+
<DebugSymbols>true</DebugSymbols>
18+
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
19+
</PropertyGroup>
20+
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
21+
<DebugSymbols>true</DebugSymbols>
22+
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
23+
</PropertyGroup>
24+
<ItemGroup>
25+
<Compile Include="stable_diffusion.py" />
26+
<Compile Include="stable_diffusion_adapter.py" />
27+
</ItemGroup>
28+
<ItemGroup>
29+
<Content Include="explore.html" />
30+
<Content Include="install.bat" />
31+
<Content Include="install.sh" />
32+
<Content Include="modulesettings.json" />
33+
<Content Include="requirements.cuda11.txt" />
34+
<Content Include="requirements.cuda12.txt" />
35+
<Content Include="requirements.macos.arm64.txt" />
36+
<Content Include="requirements.macos.txt" />
37+
<Content Include="requirements.txt" />
38+
</ItemGroup>
39+
<ItemGroup>
40+
<Interpreter Include="bin\windows\python39\venv\">
41+
<Id>venv</Id>
42+
<Version>3.9</Version>
43+
<Description>venv (Python 3.9 (64-bit))</Description>
44+
<InterpreterPath>Scripts\python.exe</InterpreterPath>
45+
<WindowsInterpreterPath>Scripts\pythonw.exe</WindowsInterpreterPath>
46+
<PathEnvironmentVariable>PYTHONPATH</PathEnvironmentVariable>
47+
<Architecture>X64</Architecture>
48+
</Interpreter>
49+
</ItemGroup>
50+
<ItemGroup>
51+
<Folder Include="assets\" />
52+
</ItemGroup>
53+
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets" />
54+
<!-- Uncomment the CoreCompile target to enable the Build command in
55+
Visual Studio and specify your pre- and post-build commands in
56+
the BeforeBuild and AfterBuild targets below. -->
57+
<!--<Target Name="CoreCompile" />-->
58+
<Target Name="BeforeBuild">
59+
</Target>
60+
<Target Name="AfterBuild">
61+
</Target>
62+
</Project>

explore.html

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
<!DOCTYPE html>
2+
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
3+
<!--
4+
CODEPROJECT.AI SERVER MODULE EXPLORER
5+
6+
This page provides the means to test this module using the same infrastructure as
7+
the CodeProject.AI Server explorer. This page also provides the UI elements that
8+
the explorer will parse and use to build up the UI of the main explorer itself.
9+
10+
RULES AND CONVENTIONS
11+
12+
1. This page should provide sufficient functionality to test and explore this
13+
module.
14+
15+
2. This page should use the functionality in the explorer.js file so that when
16+
the elements of this page are inserted into the main explorer, it all works
17+
seamlessly. Specifically, you will probably use
18+
19+
- clearImagePreview: Clears the image preview area.
20+
- previewImage: Displays an image in the shared image preview area and takes a
21+
input[type=file] as parameter.
22+
- submitRequest: Sends a request to the AI server.
23+
- setResultsHtml: Sets the HTML in the shared 'results' element. Parameter is the HTML
24+
to display.
25+
- getProcessingMetadataHtml: Gets HTML representing the common data returned from a call to a
26+
module.
27+
- displayBaseResults: Displays the common data returned from a call to a module.
28+
- showPredictionSummary: Displays in the shared HTML results pane the list of predictions
29+
returned from an inference operation.
30+
- clearImageResult: Clears the image result area
31+
- showResultsImageData: Displays an image in the shared image results area using the data
32+
returned from a call to a module, and overlays bounding boxes if
33+
present in the data
34+
- showResultsBoundingBoxes: Displays bounding boxes on the shared image results area based on
35+
the boxes returned in the predictions parameter. The first param is
36+
an array of predictions returned from a computer vision operation.
37+
38+
3. There are 3 parts of this page that will be pulled into the main explorer
39+
during runtime: The HTML, the script, and the CSS. These sections are bounded by
40+
41+
- HTML: START EXPLORER MARKUP / END EXPLORER MARKUP pair, each within HTML comment brackets
42+
- Script: START EXPLORER SCRIPT / END EXPLORER SCRIPT pair, each as a // comment on its own line
43+
- CSS: START EXPLORER STYLE / END EXPLORER STYLE pair, each inside /* ... */ comments
44+
45+
These delimiters should be on a line by themselves
46+
47+
4. **Please provide output elements to display the results of operations** if
48+
you wish to use the standard HTML / Image results elements in the main explorer
49+
50+
- For HTML output, include a DIV with id 'results'
51+
- For Image preview, include an IMG element with id imgPreview
52+
- For image results, include an IMG with element imgPreview and a DIV with
53+
id 'imageMask'.
54+
- You can use a single image for both preview and results if you wish by only
55+
including a imgPreview image. Make sure you have the imageMask DIV though.
56+
- For Sound preview, include an AUDIO element with id 'snd' that contains a
57+
SOURCE tag
58+
59+
5. When this file is parsed and injected into the larger explorer, the HTML is
60+
injected first, then the script, then the CSS.
61+
62+
6. **To ensure uniqueness of elements** you can include the _MID_ macro in any
63+
name. This will be expanded to be [ModuleId]_ where [ModuleId] is the literal
64+
ID of this module. For instance <div id="_MID_TextBox"> becomes <div id="MyModuleId_TextBox">
65+
-->
66+
<head>
67+
<meta charset="utf-8" />
68+
<title>Text2Image Module Test</title>
69+
70+
<link id="bootstrapCss" rel="stylesheet" type="text/css" href="http://localhost:32168/assets/bootstrap-dark.min.css">
71+
<!--<link rel="stylesheet" type="text/css" href="http://localhost:32168/assets/server.css?v=2.5.0.0">-->
72+
<script type="text/javascript" src="http://localhost:32168/assets/server.js"></script>
73+
<script type="text/javascript" src="http://localhost:32168/assets/explorer.js"></script>
74+
75+
<style>
76+
/* START EXPLORER STYLE */
77+
/* END EXPLORER STYLE */
78+
</style>
79+
80+
</head>
81+
<body class="dark-mode">
82+
<div class="mx-auto" style="max-width: 800px;">
83+
<h2 class="mb-3">Text2Image Module Test</h2>
84+
<form method="post" action="" enctype="multipart/form-data" id="myform">
85+
86+
<!-- START EXPLORER MARKUP -->
87+
<div class="form-group row">
88+
<div>
89+
<label for="_MID_prompt" class="col-form-label col-2">Prompt</label>
90+
<textarea id="_MID_prompt" class="w-100" style="height:100px"
91+
title="The prompt to be used by Stable Diffusion to create the image"></textarea>
92+
</div>
93+
<div>
94+
<label for="_MID_negative_prompt" class="col-form-label">Negative Prompt</label>
95+
<textarea id="_MID_negative_prompt" class="w-100" style="height:100px"
96+
title="The negative prompt to be used by Stable Diffusion to create the image"></textarea>
97+
</div>
98+
99+
<div class="row mb-3">
100+
<div class="col-4">
101+
<label for"_MID_num_images" class="form-label">Images</label>
102+
<input type="number" id="_MID_num_images" class="form-control"
103+
min="1" max="4" steps="1" value="1" title="The number of images to generate. Defaults to 1."/>
104+
</div>
105+
<div class="col-4">
106+
<label for="_MID_seed" class="form-label">Seed</label>
107+
<input id="_MID_seed" class="form-control" type="number" value="0"
108+
title="The seed to use for the diffusion random number generator. If Fixed is checked will use this value, otherwise uses random value."/>
109+
<label for="_MID_seed_fixed" class="form-check-label" >Fixed</label>
110+
<input id="_MID_seed_fixed" class="form-check-input ms-2" type="checkbox"
111+
title="If checked, will use the value above rather than a random value. This allows for reproducible image generation."/>
112+
</div>
113+
<div class="col-4">
114+
<label for="_MID_num_steps" class="form-label">Steps</label>
115+
<input type="number" id="_MID_num_steps" class="form-control" min="1" max="100"
116+
steps="1" value="40" title="The number of inference steps to run"/>
117+
</div>
118+
</div>
119+
<div class="row mb-3">
120+
<div class="col-4">
121+
<label for="_MID_guidance" class="form-label">Guidance</label>
122+
<input type="number" id="_MID_guidance" class="form-control" min="0.0" max="20.0"
123+
steps="0.1" value="7" title="How well the process aligns with the prompt for image generation (0.0 - 20.0)."/>
124+
</div>
125+
<div class="col-4">
126+
<label for="_MID_width" class="form-label">Width</label>
127+
<input type="number" id="_MID_width" class="form-control" min="128" max="1024"
128+
steps="8" value="512" title="The width of the image to be created. Defaults to 512. Must be a multiple of 8."/>
129+
</div>
130+
<div class="col-4">
131+
<label for="_MID_height" class="form-label">Height</label>
132+
<input type="number" id="_MID_height" class="form-control" min="128" max="1024"
133+
steps="8" value="512" title="The height of the image to be created. Must be a multiple of 8."/>
134+
</div>
135+
</div>
136+
<input id="_MID_generte" class="form-control btn-success" type="button" value="Generate Image"
137+
style="width:11rem" onclick="_MID_onGenerateImages()" />
138+
</div>
139+
<hr>
140+
<!-- END EXPLORER MARKUP -->
141+
142+
<div class="w-100 position-relative form-control my-4 p-0">
143+
<div id="imgMask" class="position-absolute"
144+
style="left:0;top:0;pointer-events:none;z-index:10"></div>
145+
<img src="" id="imgPreview" class="w-100" style="height:250px;visibility:hidden">
146+
</div>
147+
<div>
148+
<h2>Results</h2>
149+
<div id="results" name="results" class="bg-light p-3" style="min-height: 100px;"></div>
150+
</div>
151+
152+
</form>
153+
154+
<script type="text/javascript">
155+
// START EXPLORER SCRIPT
156+
157+
async function _MID_onGenerateImages() {
158+
159+
clearImagePreview();
160+
161+
if (!_MID_prompt.value) {
162+
alert("No image prompt specified");
163+
return;
164+
}
165+
166+
setResultsHtml("Generating Images...");
167+
let params = [['prompt', _MID_prompt.value],
168+
['num_images_per_prompt', _MID_num_images.value],
169+
['seed', _MID_seed_fixed.checked ? _MID_seed.value : null],
170+
['num_inference_steps', _MID_num_steps.value],
171+
['guidance_scale', _MID_guidance.value],
172+
['width', _MID_width.value],
173+
['height', _MID_height.value]];
174+
175+
if (_MID_negative_prompt.value != "") {
176+
params.push(['negative_prompt', _MID_negative_prompt.value]);
177+
}
178+
179+
let data = await submitRequest('text2image', 'create', null, params);
180+
if (data) {
181+
// get the commandId to so we can poll for the results
182+
_MID_commandId = data.commandId;
183+
_MID_moduleId = data.moduleId;
184+
185+
params = [['commandId', _MID_commandId], ['moduleId', _MID_moduleId]];
186+
done = false;
187+
loopCount = 0;
188+
spinner = "|/-\\";
189+
190+
while (!done) {
191+
192+
await delay(1000);
193+
194+
let results = await submitRequest('text2image', 'get_command_status', null, params);
195+
if (results && results.success) {
196+
197+
if (results.commandStatus == "failed") {
198+
done = true;
199+
setResultsHtml(results?.error || "Unknown error");
200+
}
201+
else {
202+
let message = results.message;
203+
if (results.commandStatus == "completed") {
204+
done = true;
205+
_MID_seed.value = results?.seed || 0;
206+
}
207+
else {
208+
spinChar = spinner.charAt(loopCount++ % spinner.length);
209+
message = spinChar + " " + message;
210+
}
211+
212+
setResultsHtml(message);
213+
214+
if (results.images && results.images.length > 0)
215+
showResultsImage(results.images[0], results.width, results.height);
216+
}
217+
}
218+
else {
219+
// TODO: check for timeouts and other network errors.
220+
done = true;
221+
// setResultsHtml(results?.error || "No response from server");
222+
}
223+
}
224+
};
225+
}
226+
227+
// =====================================================================
228+
// Startup
229+
230+
231+
// END EXPLORER SCRIPT
232+
</script>
233+
</div>
234+
</body>
235+
</html>

install.bat

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
@if "%1" NEQ "install" (
2+
echo This script is only called from ..\..\setup.bat
3+
@pause
4+
@goto:eof
5+
)
6+
7+
REM Download the YOLO models from the CodeProject models/ folder and store in /assets
8+
REM call "%sdkScriptsDirPath%\utils.bat" GetFromServer "models/" "models-yolo8-pt.zip" "assets" "Downloading Standard YOLO models..."

install.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
if [ "$1" != "install" ]; then
2+
read -t 3 -p "This script is only called from: bash ../../setup.sh"
3+
echo
4+
exit 1
5+
fi
6+
7+
# Download the YOLO models from the CodeProject models/ folder and store in /assets
8+
# getFromServer "models/" "models-yolo8-pt.zip" "assets" "Downloading Standard YOLO models..."

0 commit comments

Comments
 (0)