Для рисования с помощью искусственного интеллекта требуются мощные данные и вычислительная мощность. Только хорошо обученные алгоритмы и наборы данных могут создавать выдающиеся работы. Однако это имеет более высокий порог для людей, которые хотят изучить рисование с помощью ИИ. Пока я не обнаружил продукт Tencent Cloud для рисования с использованием искусственного интеллекта, который после активации включает 500 бесплатных изображений. После его использования покупка 1000 изображений стоит менее 30. После некоторого использования я почувствовал, что это довольно хорошо. Раньше создавать его самостоятельно с использованием SD было трудоемким и дорогостоящим занятием, не говоря уже о трудоемкой среде и обучении. Производительность сервера была недостаточной в пиковый период, когда рабочая нагрузка была большой, а задач не было. сервер в течение минимального периода, что стоит денег. Теперь это намного лучше. Это можно легко сделать без сервера графического процессора. Время прорисовки очень стабильно, независимо от пиков и спадов, а повышенная гибкость и стоимость значительно сокращаются.
В сочетании с функцией EdgeOne программа вызова рисования AI запускается через пограничные узлы, близкие к пользователю, что не только устраняет необходимость в серверах, но и повышает скорость доступа.
ВходитьКонсоль для рисования с искусственным интеллектом,Нажмите Открыть сейчас.
После активации будет предоставлено 500 бесплатных кредитов. Если вы купите новый, в настоящее время есть активности.
Например, у меня есть это1000Чжан здесьэтотКупил для мероприятия:
29.9 можно купить 1000 штук, и каждая штука стоит менее 3 центов, что по-прежнему очень рентабельно.
ВходитьУправление ключами API,Создать новый ключ
Затем нажмите кнопку отображения справа от сгенерированного ключа и отсканируйте код с администратором WeChat.
Запишите полученные SecretId и SecretKey.
Звонок разделен на 4 этапа:
1. Объединить параметры запроса
2. Подпишите запрос, используя свой ключ API.
3. Прикрепите результат подписи к заголовку запроса.
4. Отправить запрос
ИИ живописьAPIСсылка на документацию:https://cloud.tencent.com/document/api/1668/88064
Ниже представлена сводная таблица
Имя параметра | Позиция параметра | Формат и инструкции | Пример |
---|---|---|---|
Action | Заголовок запроса | Строка, фиксированное значение | TextToImage |
Version | Заголовок запроса | Строка, фиксированное значение | 2022-12-29 |
Region | Заголовок запроса | Строка, регион | ap-guangdong |
Prompt | Тело запроса в формате JSON | Строка, описание чертежа | Голубое небо и белые облака, крупный рогатый скот и овцы на лугах |
NegativePrompt | Тело запроса в формате JSON | Строка, обратное описание | горы и реки |
Styles | Тело запроса в формате JSON | Тип массива, стиль рисования | [“103”] |
ResultConfig | Тело запроса в формате JSON | Тип словаря, конфигурация результатов (например, размер изображения) | {“Resolution”:”768:1024”} |
Полный код выглядит следующим образом:
Есть 3 позиции модификации:
1. API-ключ SecretId, полученный выше.
2. API-ключ SecretKey, полученный выше.
3. Ключ доступа. Во избежание несанкционированных звонков со стороны других лиц не оставляйте это поле пустым.
// Кодировать строку в ArrayBuffer
function stringToArrayBuffer(str) {
const encoder = new TextEncoder();
return encoder.encode(str);
}
// Преобразовать ArrayBuffer в шестнадцатеричную строку
function arrayBufferToHexString(arrayBuffer) {
const byteArray = new Uint8Array(arrayBuffer);
const hexCodes = [...byteArray].map(value => value.toString(16).padStart(2, '0'));
return hexCodes.join('');
}
async function hmacSHA256(key, data) {
const importedKey = await crypto.subtle.importKey(
'raw',
key,
{ name: 'HMAC', hash: 'SHA-256' },
false,
['sign']
);
const msgBuffer = stringToArrayBuffer(data);
const signatureBuffer = await crypto.subtle.sign('HMAC', importedKey, msgBuffer);
return signatureBuffer;
}
function uint8ArrayToHex(array) {
return Array.from(array).map(byte => byte.toString(16).padStart(2, '0')).join('');
}
// Алгоритм подписи
async function qcloud_v3_post(SecretId,SecretKey,Service,bodyString,headersOper) {
const HTTPRequestMethod = "POST"
const CanonicalURI = "/"
const CanonicalQueryString = ""
// Воля JSON нажатие клавиши на объекте ASCII Сортировать по возрастанию
let sortedheadersOper = Object.keys(headersOper).filter(key => (key.toLowerCase() !== "x-tc-version")).sort();
// Перебирать отсортированные ключи и объединять их.
let SignedHeaders = sortedheadersOper.map(key => key.toLowerCase()).join(";");
let CanonicalHeaders = sortedheadersOper.map(key => key.toLowerCase() + ":" + headersOper[key].toLowerCase()).join("\n");
CanonicalHeaders = CanonicalHeaders + "\n"
let HashedRequestPayload = await sha256(bodyString)
const CanonicalRequest =
HTTPRequestMethod + '\n' +
CanonicalURI + '\n' +
CanonicalQueryString + '\n' +
CanonicalHeaders + '\n' +
SignedHeaders + '\n' +
HashedRequestPayload
const currentDate = new Date();
const year = currentDate.getUTCFullYear();
const month = (currentDate.getUTCMonth() + 1).toString().padStart(2, '0');
const day = currentDate.getUTCDate().toString().padStart(2, '0');
const formattedDate = `${year}-${month}-${day}`;
const Algorithm = "TC3-HMAC-SHA256"
// Получить текущую временную метку второго уровня
const RequestTimestamp = Math.floor(Date.now() / 1000).toString();
// const RequestTimestamp = "1688025007"
const CredentialScope = formattedDate + "/" + Service + "/tc3_request"
const HashedCanonicalRequest = await sha256(CanonicalRequest)
const StringToSign =
Algorithm + '\n' +
RequestTimestamp + '\n' +
CredentialScope + '\n' +
HashedCanonicalRequest
const SecretDate = await hmacSHA256(new Uint8Array([...stringToArrayBuffer("TC3"), ...new Uint8Array(SecretKey)]), formattedDate);
const SecretService = await hmacSHA256(SecretDate, Service);
const SecretSigning = await hmacSHA256(SecretService, "tc3_request");
const Signature = arrayBufferToHexString(await hmacSHA256(SecretSigning, StringToSign));
const Authorization =
Algorithm + ' ' +
'Credential=' + SecretId + '/' + CredentialScope + ', ' +
'SignedHeaders=' + SignedHeaders + ', ' +
'Signature=' + Signature
headersOper["X-TC-Timestamp"] = RequestTimestamp;
headersOper["Authorization"] = Authorization;
return headersOper
}
// sha256 Сводка подписей
async function sha256(message) {
const msgBuffer = new TextEncoder().encode(message);
const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);
return uint8ArrayToHex(new Uint8Array(hashBuffer));
}
// Ключевая позиция заполнения
const SecretId = "";
const SecretKey = stringToArrayBuffer("");
const Service = "aiart";
// Доступ к ключевым настройкам
const acckey = ","
async function handleRequest(request) {
const json = await request.json()
const text2imgjson = {}
if(json.Acckey !== acckey){
return new Response(JSON.stringify({"code":1,"msg":"Ошибка ключа"}, null, 2), {
headers: { 'Content-Type': 'application/json',
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
'Access-Control-Max-Age': '86400',
'Access-Control-Allow-Origin': '*' },
status: 200
})
}
text2imgjson["Prompt"] = json.Prompt
if(json.NegativePrompt !== ""){
text2imgjson["NegativePrompt"] = json.NegativePrompt
}
if(json.Styles !== ""){
text2imgjson["Styles"] = [json.Styles]
}
if(json.Size !== ""){
text2imgjson["ResultConfig"] = {"Resolution":json.Size}
}
const headersPending = {
'Host': 'aiart.tencentcloudapi.com',
'Content-Type': 'application/json',
'X-TC-Action': 'TextToImage',
'X-TC-Version': '2022-12-29',
'X-TC-Region': 'ap-guangzhou',
};
const bodyString = JSON.stringify(text2imgjson)
const headers = await qcloud_v3_post(SecretId,SecretKey,Service,bodyString,headersPending)
const url1 = 'https://aiart.tencentcloudapi.com/';
let qcloud_api_data;
await fetch(url1, {
method: 'POST',
headers: headers,
body: bodyString
})
.then(response => response.json())
.then(data => qcloud_api_data = data)
.catch(error => qcloud_api_data = error);
let ResponseData = {};
if(qcloud_api_data["Response"]["Error"] === undefined){
ResponseData["code"] = 0;
ResponseData["image"] = "data:image/jpg;base64," + qcloud_api_data["Response"]["ResultImage"]
}else{
ResponseData["code"] = 1;
ResponseData["msg"] = qcloud_api_data["Response"]["Error"]["Message"]
ResponseData["RequestId"] = qcloud_api_data["Response"]["RequestId"]
}
return new Response(JSON.stringify(ResponseData, null, 2), {
headers: { 'Content-Type': 'application/json',
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
'Access-Control-Max-Age': '86400',
'Access-Control-Allow-Origin': '*' },
status: 200
})
}
// Обработка предполетной подготовки
async function handleOptions(request) {
const headers = {
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
'Access-Control-Max-Age': '86400',
'Access-Control-Allow-Origin': '*'
}
return new Response(null, {
headers: headers
})
}
addEventListener('fetch', (event) => {
if (event.request.method === 'OPTIONS') {
event.respondWith(handleOptions(event.request))
} else {
event.respondWith(handleRequest(event.request))
}
});
Отображение изображения с эффектом:
Исходный код:
Не забудьте заменить URL-адрес API
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AIРисунок</title>
<style>
body {
font-family: Arial, sans-serif;
}
.container {
display: flex;
justify-content: center;
}
.box {
margin: 20px;
border: none; /* Удалить границу поля */
padding: 10px;
background-color: #f5f5f5; /* Установите цвет фона поля */
border-radius: 10px; /* Добавьте закругленные углы */
display: flex; /* Используйте гибкий макет */
flex-direction: column; /* вертикальная планировка */
align-items: center; /* выравнивание по центру */
text-align: center; /* характервыравнивание по центру */
}
.box:nth-child(2) {
align-self: start; /* Выровняйте верхнюю часть правого поля */
}
.box-title {
margin-bottom: 10px;
border-bottom: 1px solid grey; /* Добавьте разделитель внизу заголовка */
padding-bottom: 5px; /* Добавьте немного нижнего интервала, чтобы усилить визуальный эффект. */
}
#image-container {
width: 300px;
height: 380px;
background-color: #eee;
margin: auto; /* Центрировать по горизонтали внутри родительского элемента */
background-image: none;
}
#text-description {
width: 300px;
height: 100px;
margin-bottom: 10px;
border: 1px solid grey; /* Добавить внешнюю границу */
padding: 5px;
resize: none; /* Отключить изменение размера */
font-size: 14px;
outline: none; /* Удалить внешнюю границу поля ввода по умолчанию. */
border-radius: 0; /* Убрать закругленные углы */
}
#text-description2 {
width: 300px;
height: 100px;
margin-bottom: 10px;
border: 1px solid grey; /* Добавить внешнюю границу */
padding: 5px;
resize: none; /* Отключить изменение размера */
font-size: 14px;
outline: none; /* Удалить внешнюю границу поля ввода по умолчанию. */
border-radius: 0; /* Убрать закругленные углы */
}
#dropdown {
padding: 10px 20px; /* Увеличить отступ кнопок */
cursor: pointer;
margin-bottom: 10px;
border: 1px solid grey; /* Добавить внешнюю границу */
width: 100%; /* Ширина воли установлена на 100% для выравнивания по контейнеру. */
align-self: flex-start; /* Кнопка выровнена по левому краю */
}
#dropdown2 {
padding: 10px 20px; /* Увеличить отступ кнопок */
cursor: pointer;
margin-bottom: 10px;
border: 1px solid grey; /* Добавить внешнюю границу */
width: 100%; /* Ширина воли установлена на 100% для выравнивания по контейнеру. */
align-self: flex-start; /* Кнопка выровнена по левому краю */
}
#acckey {
padding: 10px 20px; /* Увеличить отступ кнопок */
cursor: pointer;
margin-bottom: 10px;
border: 1px solid grey; /* Добавить внешнюю границу */
width: 100%; /* Ширина воли установлена на 100% для выравнивания по контейнеру. */
align-self: stretch; /* Кнопка выровнена по левому краю */
}
#input-container {
flex-grow: 1;
display: flex;
flex-direction: column; /* вертикальная планировка */
align-items: center; /* выравнивание по центру */
}
#text-input {
width: 300px;
height: 30px;
margin-bottom: 10px;
}
#generate-button {
padding: 10px 20px; /* Увеличить отступ кнопок */
background-color: #4caf50;
color: white;
border: none;
cursor: pointer;
width: 100%; /* Ширина воли установлена на 100% для выравнивания по контейнеру. */
align-self: flex-start; /* Кнопка выровнена по левому краю */
}
@media (max-width: 600px) {
.container {
flex-wrap: wrap; /* Перенос отображения при недостаточной ширине экрана */
}
.box {
width: 100%; /* Заставьте поле заполнить одну строку */
margin-bottom: 20px; /* Добавить нижнее поле */
}
}
</style>
</head>
<body>
<div class="container">
<div class="box">
<h2 class="box-title">Рисунокрезультат</h2>
<div id="image-container"></div>
</div>
<div class="box">
<h2 class="box-title">текстовое описание</h2>
<div id="input-container">
<textarea id="text-description" title="Текстовое описание" Placeholder="Текстовое описание.
алгоритмВоляИнтеллектуальное создание изображений, связанных с входным текстом。Рекомендуется подробно описать тематику экрана.、деталь、Сцены и т. д.,Чем богаче текстовое описание,Тем красивее создаваемый эффект.
не может быть пустым,Рекомендуется использовать китайский。Самые загружаемые512персонажи。"></textarea>
<textarea id="text-description2" title="Обратное текстовое описание" Placeholder="обратное текстовое описание.
Он используется для того, чтобы в определенной степени направить направление генерации модели с противоположной стороны и уменьшить вероятность появления описательного содержания в сгенерированных результатах, но полностью исключить его нельзя.
Рекомендуется использовать китайский。Самые загружаемые512персонажи。"></textarea>
<select id="dropdown" title="разрешение">
<option value="768:1024">разрешение(по умолчанию768:1024)</option>
<option value="768:768">768:768</option>
<option value="1024:768">1024:768</option>
</select>
<select id="dropdown2" title="стиль живописи">
<option value="201">стиль живописи(по умолчаниюЯпонский стиль аниме)</option>
<option value="202">монстр стиль</option>
<option value="301">Игровой мультяшный рисунок руки</option>
<option value="101">живопись тушью</option>
<option value="102">концепт-арт</option>
<option value="103">рисование</option>
<option value="104">акварельная живопись</option>
<option value="106">стиль импасто</option>
<option value="107">иллюстрация</option>
<option value="108">стиль вырезки из бумаги</option>
<option value="109">Импрессионизм</option>
<option value="110">2.5Dпортрет</option>
<option value="111">портрет</option>
<option value="112">черно-белый эскиз</option>
<option value="113">киберпанк</option>
<option value="114">стиль научной фантастики</option>
<option value="000">Не ограничивается стилем</option>
</select>
<div style="display: flex; justify-content: flex-start; width: 100%;">
<input id="acckey" type="password" Placeholder="Ключ доступа" style="width: 100%;">
</div>
<button id="generate-button">генерировать</button>
</div>
</div>
</div>
<script>
document.getElementById("generate-button").addEventListener("click", function() {
var Ai_Image_Prompt = document.getElementById("text-description").value;
var Ai_Image_NegativePrompt = document.getElementById("text-description2").value;
var Ai_Image_Size = document.getElementById("dropdown").value;
var Ai_Image_Styles = document.getElementById("dropdown2").value;
var Ai_Image_AccKey = document.getElementById("acckey").value;
if(Ai_Image_Prompt === ""){
alert("Описание изображения пустое");
return;
}
if(Ai_Image_AccKey === ""){
alert("Ключ доступа пуст");
return;
}
var data = {
"Prompt": Ai_Image_Prompt,
"NegativePrompt": Ai_Image_NegativePrompt,
"Styles": Ai_Image_Styles,
"Size": Ai_Image_Size,
"Acckey": Ai_Image_AccKey
};
var xhr = new XMLHttpRequest();
xhr.open("POST", "https://api.9kr.cc/qcloud/text2img", true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function() {
if(xhr.readyState === 4){
if (xhr.status === 200) {
var response = JSON.parse(xhr.responseText);
if (response.code === 0) {
var imageContainer = document.getElementById("image-container");
imageContainer.style.backgroundImage = "url(" + response.image + ")";
imageContainer.style.backgroundSize = "contain";
var img = new Image();
img.onload = function() {
var imageWidth = this.width;
var imageHeight = this.height;
var containerWidth = imageContainer.offsetWidth;
var adjustedHeight = (containerWidth / imageWidth) * imageHeight;
imageContainer.style.height = adjustedHeight + "px";
};
img.src = response.image;
} else {
alert(response.msg);
}
}else{
alert("Ошибка запроса:" + xhr.status);
}
}
};
xhr.onerror = function() {
// Обработка сетевых ошибок
Предупреждение("Ошибка сети");
};
xhr.send(JSON.stringify(data));
});
</script>
</body>
</html>
Купить пакет EdgeOne,Ссылка на покупку:https://buy.cloud.tencent.com/edgeone
ВходитьEdgoOneКонсоль добавлена:https://console.cloud.tencent.com/edgeone/zones/
Следует отметить только один момент: при привязке пакета выберите привязку купленного пакета, и вы увидите только что приобретенный пакет.
После добавления сайта выберите «Служба доменных имен» → «Управление доменными именами» → «Добавить доменное имя» и добавьте два доменных имени.
1. ai.xxxx.com --- используется для размещения интерфейса
2. api.xxx.com --- используется для размещения серверной части
ps на самом деле можно добавить доменное имя и потом обрабатывать информацию отдельно по пути, но управлять этим неудобно.
Нажмите «Пограничная функция» → «Управление функциями» → «Добавить функцию», чтобы добавить две функции соответственно.
Функция 1 используется для отображения главной страницы, которая является предыдущей страницей ai.xxx.com.
Войдите на страницу добавления функции
Код функции следующий:
Воляпереднийвнешний URL-адрес API в коде: " https://api.9kr.cc/qcloud/text2img”Заменить наhttps://api.xxx.com,Затем вставьте следующий код,Затем перейдите в поле кода функции на рисунке выше.
const html = `
Заполните здесь внешний вид, показанный выше. код
`;
async function handleRequest(request) {
return new Response(html, {
headers: {
'content-type': 'text/html; charset=UTF-8',
'x-edgefunctions-test': 'Welcome to use Edge Functions.',
},
});
}
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});
После нажатия «Создать и развернуть» нажмите «Добавить триггерное правило».
Во всплывающем окне выберите HOSTà равно àai.xxx.com, а затем нажмите OK.
Вторая функция используется для обработки запросов на внешний интерфейс и возврата результатов рисования (предыдущий api.xxx.com).
Создайте новую функцию, например «Функция 1», затем скопируйте код после изменения ключа API и ключа доступа на шаге 4 и, наконец, установите HOST, который запускает правило, на «api.xxx.com».
После выполнения вышеуказанных операций откройте ai.9kr.cc и вы увидите следующий интерфейс:
Введите текстовое описание и ключ доступа, указанный выше, и нажмите «Создать»:
На этом станция рисования ИИ завершена.
Помимо рисования ИИ, Tencent Cloud также предоставляет бесплатные пробные версии для многих продуктов ИИ, и эта серия продуктов должна быть завершена позже.
Ниже приведен список бесплатных пробных продуктов.
Если вам интересно, вы можете нажать на эту ссылку, чтобы узнать больше: https://cloud.tencent.com/act/free?from=20893