init
8
.idea/.gitignore
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
6
.idea/inspectionProfiles/profiles_settings.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
17
.idea/jupyter-settings.xml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="JupyterPersistentConnectionParameters">
|
||||||
|
<option name="moduleParameters">
|
||||||
|
<map>
|
||||||
|
<entry key="$PROJECT_DIR$/.idea/pythonProject.iml">
|
||||||
|
<value>
|
||||||
|
<JupyterConnectionParameters>
|
||||||
|
<option name="managed" value="true" />
|
||||||
|
<option name="sdkName" value="Python 3.10 (pythonProject)" />
|
||||||
|
</JupyterConnectionParameters>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
7
.idea/misc.xml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Black">
|
||||||
|
<option name="sdkName" value="Python 3.10 (pythonProject)" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (pythonProject)" project-jdk-type="Python SDK" />
|
||||||
|
</project>
|
8
.idea/modules.xml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/pythonProject.iml" filepath="$PROJECT_DIR$/.idea/pythonProject.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/other.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="PySciProjectComponent">
|
||||||
|
<option name="PY_INTERACTIVE_PLOTS_SUGGESTED" value="true" />
|
||||||
|
</component>
|
||||||
|
</project>
|
8
.idea/pythonProject.iml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
106
.ipynb_checkpoints/image_classification_dataset-checkpoint.ipynb
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"metadata": {},
|
||||||
|
"cell_type": "raw",
|
||||||
|
"source": "MNIST数据集 (LeCun et al., 1998) 是图像分类中广泛使用的数据集之一,但作为基准数据集过于简单。 我们将使用类似但更复杂的Fashion-MNIST数据集 (Xiao et al., 2017)。",
|
||||||
|
"id": "58ac648c45d06f50"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"ExecuteTime": {
|
||||||
|
"end_time": "2024-05-19T04:24:31.687065Z",
|
||||||
|
"start_time": "2024-05-19T04:24:22.281131Z"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cell_type": "code",
|
||||||
|
"source": [
|
||||||
|
"import tensorflow as tf\n",
|
||||||
|
"from d2l import tensorflow as d2l\n",
|
||||||
|
"\n",
|
||||||
|
"d2l.use_svg_display()"
|
||||||
|
],
|
||||||
|
"id": "4f19e5d16d0a7341",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"2024-05-19 12:24:22.318857: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: SSE4.1 SSE4.2 AVX AVX2 FMA\n",
|
||||||
|
"To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"execution_count": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metadata": {},
|
||||||
|
"cell_type": "raw",
|
||||||
|
"source": [
|
||||||
|
"3.5.1. 读取数据集\n",
|
||||||
|
"我们可以通过框架中的内置函数将Fashion-MNIST数据集下载并读取到内存中。"
|
||||||
|
],
|
||||||
|
"id": "c67a3433075cb8ed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metadata": {},
|
||||||
|
"cell_type": "code",
|
||||||
|
"outputs": [],
|
||||||
|
"execution_count": null,
|
||||||
|
"source": "mnist_train, mnist_test = tf.keras.datasets.fashion_mnist.load_data()",
|
||||||
|
"id": "e5defd40322a3af2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metadata": {},
|
||||||
|
"cell_type": "raw",
|
||||||
|
"source": "Fashion-MNIST由10个类别的图像组成, 每个类别由训练数据集(train dataset)中的6000张图像 和测试数据集(test dataset)中的1000张图像组成。 因此,训练集和测试集分别包含60000和10000张图像。 测试数据集不会用于训练,只用于评估模型性能。",
|
||||||
|
"id": "9f2c0b217b6b5e30"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metadata": {},
|
||||||
|
"cell_type": "code",
|
||||||
|
"outputs": [],
|
||||||
|
"execution_count": null,
|
||||||
|
"source": "len(mnist_train[0]), len(mnist_test[0])",
|
||||||
|
"id": "6129edd7e9c7e9fc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metadata": {},
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"source": [
|
||||||
|
"每个输入图像的高度和宽度均为28像素。 数据集由灰度图像组成,其通道数为1。 为了简洁起见,本书将高度\n",
|
||||||
|
"h像素、宽度w像素图像的形状记hxw或(h,w)。"
|
||||||
|
],
|
||||||
|
"id": "719bd9e11b3b06a9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"metadata": {},
|
||||||
|
"cell_type": "code",
|
||||||
|
"outputs": [],
|
||||||
|
"execution_count": null,
|
||||||
|
"source": "mnist_train[0][0].shape",
|
||||||
|
"id": "3ed7450fafac4f36"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 2
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython2",
|
||||||
|
"version": "2.7.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
BIN
20240507153436.png
Normal file
After Width: | Height: | Size: 133 KiB |
BIN
20240507153436.png.zip
Normal file
BIN
20240507173217.png
Normal file
After Width: | Height: | Size: 414 KiB |
BIN
20240507173217.png.zip
Normal file
BIN
20240517105758.png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
20240517105800.png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
20240517105802.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
20240517105803.png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
20240517105805.png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
20240517105806.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
20240517105808.png
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
20240517105810.png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
20240517105812.png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
20240517105813.png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
20240517105815.png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
20240517105816.png
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
20240517105818.png
Normal file
After Width: | Height: | Size: 43 KiB |
BIN
20240517105820.png
Normal file
After Width: | Height: | Size: 53 KiB |
BIN
20240517105821.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
20240517105823.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
20240517105824.png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
20240517105826.png
Normal file
After Width: | Height: | Size: 53 KiB |
BIN
20240517105828.png
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
20240517105829.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
20240517115712.png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
20240517115712.tiff
Normal file
BIN
20240517135556.png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
20240517135556.tiff
Normal file
BIN
20240517140142.png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
20240517140142.tiff
Normal file
BIN
20240517140325.png
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
20240517140325.tiff
Normal file
BIN
20240517140418.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
20240517140418.tiff
Normal file
BIN
IMG_3584.png
Normal file
After Width: | Height: | Size: 5.4 MiB |
BIN
IMG_3585.png
Normal file
After Width: | Height: | Size: 5.4 MiB |
BIN
IMG_3592.png
Normal file
After Width: | Height: | Size: 6.1 MiB |
BIN
IMG_3593.png
Normal file
After Width: | Height: | Size: 9.1 MiB |
BIN
IMG_3594.png
Normal file
After Width: | Height: | Size: 2.4 MiB |
BIN
IMG_3596.png
Normal file
After Width: | Height: | Size: 1.4 MiB |
BIN
IMG_3599.tiff
Normal file
BIN
IMG_3604.png
Normal file
After Width: | Height: | Size: 748 KiB |
BIN
IMG_3606.png
Normal file
After Width: | Height: | Size: 425 KiB |
BIN
IMG_3684.png
Normal file
After Width: | Height: | Size: 632 KiB |
BIN
Sneaker.jpeg
Normal file
After Width: | Height: | Size: 150 KiB |
BIN
Sneaker.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
Snipaste_2024-05-01_21-10-47.png
Normal file
After Width: | Height: | Size: 943 KiB |
BIN
Trouser.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
WechatIMG7309.png
Normal file
After Width: | Height: | Size: 3.8 MiB |
64
check-1.py
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
import numpy as np
|
||||||
|
from numpy.fft import fft2, ifft2, fftshift, ifftshift
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
|
def modify_amplitude_only(image_path, u, v, factor):
|
||||||
|
"""
|
||||||
|
修改图像B通道在(u, v)位置的频率分量的幅度,并保持相位不变。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
image_path: 输入图像的路径。
|
||||||
|
u, v: 要修改的频率分量的位置。
|
||||||
|
factor: 幅度修改因子。
|
||||||
|
|
||||||
|
返回:
|
||||||
|
original_amplitude: 原始幅度。
|
||||||
|
modified_amplitude: 修改后的预期幅度。
|
||||||
|
current_amplitude: 实际当前幅度。
|
||||||
|
"""
|
||||||
|
# 读取图像
|
||||||
|
image = np.array(Image.open(image_path))
|
||||||
|
B_channel = image[:, :, 2] # 提取B通道
|
||||||
|
|
||||||
|
N, M = B_channel.shape
|
||||||
|
F = fftshift(fft2(B_channel))
|
||||||
|
|
||||||
|
# 获取原始的幅度和相位
|
||||||
|
original_amplitude = np.abs(F[u, v])
|
||||||
|
|
||||||
|
# 修改幅度
|
||||||
|
amplitude = np.abs(F)
|
||||||
|
phase = np.angle(F)
|
||||||
|
amplitude[u, v] *= factor
|
||||||
|
amplitude[N - u, M - v] *= factor # 确保共轭对称
|
||||||
|
modified_amplitude = amplitude[u, v]
|
||||||
|
# 重新构造频域数据
|
||||||
|
F_new = amplitude * np.exp(1j * phase)
|
||||||
|
modified_B_channel = np.real(ifft2(ifftshift(F_new))) # 执行逆FFT并取实部
|
||||||
|
|
||||||
|
# 合并修改后的B通道回原图
|
||||||
|
modified_image = image.copy()
|
||||||
|
modified_image[:, :, 2] = modified_B_channel.astype(np.float64)
|
||||||
|
|
||||||
|
# 从修改后的完整图像中提取B通道并进行DFT
|
||||||
|
modified_B_channel_from_image = modified_image[:, :, 2]
|
||||||
|
F_check = fftshift(fft2(modified_B_channel_from_image))
|
||||||
|
current_amplitude = np.abs(F_check[u, v])
|
||||||
|
|
||||||
|
return original_amplitude, modified_amplitude, current_amplitude
|
||||||
|
|
||||||
|
|
||||||
|
# 示例使用
|
||||||
|
image_path = 'demo_border.png' # 你的图像路径
|
||||||
|
u, v = 128, 128 # 选择要修改的频点位置
|
||||||
|
factor = 20 # 幅度增加因子
|
||||||
|
|
||||||
|
# 修改图像并获取数据
|
||||||
|
original_amplitude, modified_amplitude, current_amplitude = modify_amplitude_only(image_path, u, v, factor)
|
||||||
|
|
||||||
|
# 输出幅度数据对比
|
||||||
|
print(f"Original Amplitude at ({u}, {v}): {original_amplitude}")
|
||||||
|
print(f"Modified Amplitude (expected) at ({u}, {v}): {modified_amplitude}")
|
||||||
|
print(f"Current Amplitude (after modification and IFFT) at ({u}, {v}): {current_amplitude}")
|
93
check.py
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
import numpy as np
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from numpy.fft import fft2, ifft2, fftshift, ifftshift
|
||||||
|
from PIL import Image
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
def modify_b_channel_frequency(image, modify_pos, factor):
|
||||||
|
# 提取B通道并进行FFT
|
||||||
|
b_channel = image[:, :, 2]
|
||||||
|
f_b = fftshift(fft2(b_channel))
|
||||||
|
# 图像尺寸
|
||||||
|
N, M = b_channel.shape
|
||||||
|
amplitude = np.abs(f_b)
|
||||||
|
phase = np.angle(f_b)
|
||||||
|
# 获取修改位置的原始幅度
|
||||||
|
x, y = modify_pos
|
||||||
|
original_amplitude = np.abs(f_b[x, y])
|
||||||
|
|
||||||
|
# 修改指定位置的频率幅度
|
||||||
|
|
||||||
|
amplitude[x,y] = original_amplitude * factor
|
||||||
|
modified_amplitude = amplitude[x, y]
|
||||||
|
amplitude[N-x, M-y] = amplitude[N-x, M-y] * factor
|
||||||
|
# modified_amplitude = original_amplitude
|
||||||
|
f_b = amplitude * np.exp(1j * phase)
|
||||||
|
|
||||||
|
# 执行逆FFT转换回空间域
|
||||||
|
modified_b_channel = ifft2(ifftshift(f_b))
|
||||||
|
modified_b_channel = np.real(modified_b_channel)
|
||||||
|
|
||||||
|
|
||||||
|
# 保证修改后的B通道在合法范围内
|
||||||
|
# modified_b_channel = np.clip(modified_b_channel, 0, 255).astype(np.uint8)
|
||||||
|
|
||||||
|
# 合并修改后的B通道回原图
|
||||||
|
# image[:, :, 2] = modified_b_channel
|
||||||
|
|
||||||
|
# 返回修改前后的幅度信息
|
||||||
|
return image, original_amplitude, modified_amplitude, modified_b_channel
|
||||||
|
|
||||||
|
|
||||||
|
def check_modification_effect(image, modify_pos):
|
||||||
|
# 再次进行FFT以检查修改效果
|
||||||
|
# b_channel = image[:, :, 2]
|
||||||
|
b_channel = image
|
||||||
|
f_b = fftshift(fft2(b_channel))
|
||||||
|
x, y = modify_pos
|
||||||
|
current_amplitude = np.abs(f_b[x, y])
|
||||||
|
return current_amplitude, f_b
|
||||||
|
|
||||||
|
|
||||||
|
# 加载图像
|
||||||
|
img_path = 'demo_border.png'
|
||||||
|
image = np.array(Image.open(img_path))
|
||||||
|
|
||||||
|
# 设置修改位置和放大因子
|
||||||
|
modify_pos = (110, 125) # 修改位置
|
||||||
|
factor = 2 # 放大原有的幅度
|
||||||
|
|
||||||
|
# 修改B通道并检查效果
|
||||||
|
modified_image, original_amplitude, modified_amplitude, modified_b_channel = modify_b_channel_frequency(image, modify_pos, factor)
|
||||||
|
|
||||||
|
|
||||||
|
image[:, :, 2] = modified_b_channel
|
||||||
|
filename = f"{datetime.now().strftime('%Y%m%d%H%M%S')}.png"
|
||||||
|
Image.fromarray(image).save(filename)
|
||||||
|
|
||||||
|
# final_image = Image.fromarray(image)
|
||||||
|
# final_image.save(filename)
|
||||||
|
#
|
||||||
|
img = Image.open(filename)
|
||||||
|
img = np.array(img)
|
||||||
|
b_channel = img[:, :, 2]
|
||||||
|
|
||||||
|
current_amplitude, f_b = check_modification_effect(modified_b_channel, modify_pos)
|
||||||
|
|
||||||
|
|
||||||
|
# 输出幅度对比
|
||||||
|
print(f"Original Amplitude: {original_amplitude}")
|
||||||
|
print(f"Modified Amplitude (should be): {modified_amplitude}")
|
||||||
|
print(f"Current Amplitude (after modifications and IFFT): {current_amplitude}")
|
||||||
|
# 打印出f_b中最大幅度
|
||||||
|
# print(f"Maximum Amplitude in f_b: {np.max(np.abs(f_b))}")
|
||||||
|
|
||||||
|
# 可视化显示
|
||||||
|
plt.figure(figsize=(12, 6))
|
||||||
|
plt.subplot(121)
|
||||||
|
plt.imshow(image)
|
||||||
|
plt.title('Original Image')
|
||||||
|
plt.subplot(122)
|
||||||
|
plt.imshow(modified_image)
|
||||||
|
plt.title('Modified Image')
|
||||||
|
plt.show()
|
55755
color_balance_model.yml
Normal file
BIN
corrected_image.png
Normal file
After Width: | Height: | Size: 288 KiB |
BIN
corrected_image.tiff
Normal file
139
creare_pdf.py
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
import cv2
|
||||||
|
from sqlalchemy import create_engine, Table, Column, Integer, String, MetaData, DateTime,TIMESTAMP
|
||||||
|
from fpdf import FPDF
|
||||||
|
import io
|
||||||
|
import hashlib
|
||||||
|
import requests
|
||||||
|
import secrets
|
||||||
|
from PIL import Image
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import matplotlib.image as mpimg
|
||||||
|
|
||||||
|
import demo
|
||||||
|
|
||||||
|
|
||||||
|
# from demo import perspective_transform
|
||||||
|
|
||||||
|
def init_sqlserver():
|
||||||
|
# 创建连接引擎
|
||||||
|
engine = create_engine('postgresql://postgres:!1q2w3E*@8.134.85.73:5432/postgres')
|
||||||
|
# 连接数据库
|
||||||
|
connection = engine.connect()
|
||||||
|
print("Connection to PostgreSQL DB successful")
|
||||||
|
# 声明表结构
|
||||||
|
metadata = MetaData()
|
||||||
|
qrcode_data = Table('qrcode_data', metadata,
|
||||||
|
Column('key', String),
|
||||||
|
Column('circles', String),
|
||||||
|
# createdate 时间类型
|
||||||
|
Column('createdate', TIMESTAMP)
|
||||||
|
)
|
||||||
|
return qrcode_data
|
||||||
|
|
||||||
|
def get_images(key, secret, api, count=1):
|
||||||
|
images = []
|
||||||
|
urls = []
|
||||||
|
for i in range(count):
|
||||||
|
random_number = ''.join([str(secrets.randbelow(9) + 1) for _ in range(16)])
|
||||||
|
parm = f"api_key={key}&cliD={random_number}&cliT=D1&return_file={secret}"
|
||||||
|
params = {
|
||||||
|
"api_key": key,
|
||||||
|
"cliT": "D2",
|
||||||
|
"cliD": random_number,
|
||||||
|
"return_file": ""
|
||||||
|
}
|
||||||
|
# 排序
|
||||||
|
sorted_params = sorted(params.items())
|
||||||
|
concatenated_params = '&'.join(f"{key}={value}" for key, value in sorted_params)
|
||||||
|
data = concatenated_params + secret
|
||||||
|
hash_object = hashlib.md5(data.encode())
|
||||||
|
md5_hash = hash_object.hexdigest()
|
||||||
|
url = f"{api}?api_key={key}&cliT=D2&cliD={random_number}&sign={md5_hash}&return_file="
|
||||||
|
urls.append(url)
|
||||||
|
for url in urls:
|
||||||
|
response = requests.get(url)
|
||||||
|
images.append(response.content)
|
||||||
|
|
||||||
|
return images
|
||||||
|
|
||||||
|
def ndarray_to_binary(image_array):
|
||||||
|
# 将numpy数组转换为PIL图像对象
|
||||||
|
img = Image.fromarray(image_array)
|
||||||
|
# 创建一个字节流对象
|
||||||
|
byte_arr = io.BytesIO()
|
||||||
|
# 将图像保存到字节流中,格式可以自选,如PNG
|
||||||
|
img.save(byte_arr, format='PNG')
|
||||||
|
# 获取二进制数据
|
||||||
|
binary_data = byte_arr.getvalue()
|
||||||
|
return binary_data
|
||||||
|
|
||||||
|
def create_pdf(images, fileName):
|
||||||
|
# 创建 PDF 类实例
|
||||||
|
pdf = FPDF('P', 'mm', 'A4')
|
||||||
|
# 添加一页
|
||||||
|
pdf.add_page()
|
||||||
|
# 设置图片的尺寸
|
||||||
|
image_width = 15 # 图片宽度 30 mm
|
||||||
|
image_height = 15 # 图片高度 30 mm
|
||||||
|
margin = 20 # 页边距 10 mm
|
||||||
|
images_per_row = 5
|
||||||
|
# 当前行的开始位置
|
||||||
|
x_offset = margin
|
||||||
|
y_offset = margin
|
||||||
|
# 自定义临时文件路径
|
||||||
|
custom_temp_dir = './temp'
|
||||||
|
os.makedirs(custom_temp_dir, exist_ok=True)
|
||||||
|
# 循环处理图片二进制数据
|
||||||
|
for i, binary_image in enumerate(images):
|
||||||
|
if i % images_per_row == 0 and i != 0:
|
||||||
|
# 开始新的一行
|
||||||
|
x_offset = margin
|
||||||
|
y_offset += image_height + margin
|
||||||
|
# # 将binary_image保存为本地文件
|
||||||
|
# with open(f"{i}.png", "wb") as f:
|
||||||
|
# f.write(binary_image)
|
||||||
|
|
||||||
|
# 创建一个临时文件来保存图像
|
||||||
|
with tempfile.NamedTemporaryFile(delete=False, suffix=".TIFF", dir=custom_temp_dir) as tmpfile:
|
||||||
|
tmpfile.write(binary_image)
|
||||||
|
tmp_filename = tmpfile.name
|
||||||
|
print(tmp_filename)
|
||||||
|
if os.access(tmp_filename, os.R_OK):
|
||||||
|
print("File is readable.")
|
||||||
|
else:
|
||||||
|
print("File is not readable.")
|
||||||
|
|
||||||
|
img_path = demo.exec_image_result(tmp_filename)
|
||||||
|
# 将img_path返回来 tiff 格式转换 png 格式
|
||||||
|
img = Image.open(img_path)
|
||||||
|
png_path = img_path.replace('.tiff', '.png')
|
||||||
|
img.save(png_path, format='PNG')
|
||||||
|
# 添加图片
|
||||||
|
pdf.image(png_path, x=x_offset, y=y_offset, w=image_width, h=image_height)
|
||||||
|
# 更新x坐标
|
||||||
|
x_offset += image_width + margin
|
||||||
|
# 删除文件
|
||||||
|
os.remove(tmp_filename)
|
||||||
|
# 输出 PDF
|
||||||
|
pdf.output(fileName)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
key = "CL8ca5c629b676d724"
|
||||||
|
secret = "7a92463b491be3d0aa9704a8980e46ad"
|
||||||
|
api = "https://open-api.cli.im/cli-open-platform-service/v1/labelStyle/createWithKey"
|
||||||
|
|
||||||
|
# 初始化数据库
|
||||||
|
# qrcode_entity = init_sqlserver()
|
||||||
|
images = get_images(key, secret, api, count=1)
|
||||||
|
create_pdf(images, "qr_v2.pdf")
|
||||||
|
|
||||||
|
# for i in range(10):
|
||||||
|
# # 生成16位随机数字
|
||||||
|
# random_number = ''.join([str(secrets.randbelow(10)) for _ in range(16)])
|
||||||
|
# # 将随机数字每两位分为一组
|
||||||
|
# # groups = [random_number[i:i + 2] for i in range(0, len(random_number), 2)]
|
||||||
|
# # print(groups)
|
69
create_iamge_border.py
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
from PIL import Image, ImageOps
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
def add_yellow_border(image_path, output_path, border_size=2):
|
||||||
|
"""
|
||||||
|
给指定的图像添加黄色外边框并保存。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
image_path (str): 原始图像的路径。
|
||||||
|
output_path (str): 带边框的图像保存路径。
|
||||||
|
border_size (int): 边框的像素宽度,默认为2。
|
||||||
|
"""
|
||||||
|
# 打开图像
|
||||||
|
img = Image.open(image_path)
|
||||||
|
|
||||||
|
# 计算边框颜色和大小
|
||||||
|
# 灰色
|
||||||
|
# border_color = (192, 192, 192)
|
||||||
|
border_color = (255, 255, 0)
|
||||||
|
border = (border_size, border_size, border_size, border_size) # (左, 上, 右, 下)
|
||||||
|
|
||||||
|
# 添加边框
|
||||||
|
img_with_border = ImageOps.expand(img, border=border, fill=border_color)
|
||||||
|
|
||||||
|
# 保存新图像
|
||||||
|
img_with_border.save(output_path)
|
||||||
|
print(f"Image saved with a yellow border to {output_path}")
|
||||||
|
|
||||||
|
def find_qr_code_border_and_save(image_path):
|
||||||
|
# 读取图像
|
||||||
|
img = cv2.imread(image_path)
|
||||||
|
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
||||||
|
|
||||||
|
# 边缘检测
|
||||||
|
edges = cv2.Canny(gray, 50, 150, apertureSize=3)
|
||||||
|
|
||||||
|
# 霍夫变换检测直线
|
||||||
|
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, threshold=100, minLineLength=100, maxLineGap=10)
|
||||||
|
print(lines)
|
||||||
|
# 初始化最小和最大的x和y值
|
||||||
|
min_x, max_x = img.shape[1], 0
|
||||||
|
min_y, max_y = img.shape[0], 0
|
||||||
|
|
||||||
|
if lines is not None:
|
||||||
|
# 更新x和y的最小和最大值来找到边界框
|
||||||
|
for line in lines:
|
||||||
|
x1, y1, x2, y2 = line[0]
|
||||||
|
min_x = min(min_x, x1, x2)
|
||||||
|
max_x = max(max_x, x1, x2)
|
||||||
|
min_y = min(min_y, y1, y2)
|
||||||
|
max_y = max(max_y, y1, y2)
|
||||||
|
|
||||||
|
# 截取二维码区域
|
||||||
|
qr_code_region = img[min_y:max_y, min_x:max_x]
|
||||||
|
|
||||||
|
# 保存截取的图片
|
||||||
|
cv2.imwrite('qr_code_detected.png', qr_code_region)
|
||||||
|
print("二维码区域已保存为 'qr_code_detected.png'")
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("未检测到任何直线")
|
||||||
|
|
||||||
|
# 示例用法
|
||||||
|
# image_path = '20240506202950.png' # 替换为你的图像路径 jkkkkkkkkkk
|
||||||
|
# output_path = '20240506202950_border.png' # 替换为保存新图像的路径
|
||||||
|
# add_yellow_border(image_path, output_path,5)
|
||||||
|
|
||||||
|
find_qr_code_border_and_save('IMG_3565.png')
|
BIN
demo-1.png
Normal file
After Width: | Height: | Size: 8.6 KiB |
490
demo.py
Normal file
|
@ -0,0 +1,490 @@
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
from sqlalchemy import create_engine, Table, Column, Integer, String, MetaData, DateTime,TIMESTAMP
|
||||||
|
import psycopg2
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
from numpy.fft import fft2, fftshift, ifft2, ifftshift
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from PIL import Image, ImageOps
|
||||||
|
import random
|
||||||
|
from skimage.measure import label, regionprops
|
||||||
|
import math
|
||||||
|
import json
|
||||||
|
|
||||||
|
# 创建连接引擎
|
||||||
|
engine = create_engine('postgresql://postgres:!1q2w3E*@8.134.85.73:5432/postgres')
|
||||||
|
# 连接数据库
|
||||||
|
connection = engine.connect()
|
||||||
|
print("Connection to PostgreSQL DB successful")
|
||||||
|
# 声明表结构
|
||||||
|
metadata = MetaData()
|
||||||
|
qrcode_data = Table('qrcode_data', metadata,
|
||||||
|
Column('key', String),
|
||||||
|
Column('circles', String),
|
||||||
|
# createdate 时间类型
|
||||||
|
Column('createdate', TIMESTAMP)
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_filter_with_only_circles_and_generate(size, cutoff_radius, num_circles, circle_radius):
|
||||||
|
"""
|
||||||
|
创建一个仅包含指定数量圆形的滤波器。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
size: 滤波器的大小(宽度和高度相同)。
|
||||||
|
cutoff_radius: 低频区域的半径,确保所有圆都在此区域内。
|
||||||
|
num_circles: 滤波器中要生成的圆的数量。
|
||||||
|
circle_radius: 圆的半径。
|
||||||
|
|
||||||
|
返回值:
|
||||||
|
一个二进制滤波器数组,其中圆的区域值为1,其他区域值为0。
|
||||||
|
"""
|
||||||
|
filter = np.zeros((size, size)) # 初始化滤波器数组
|
||||||
|
center_x, center_y = size // 2, size // 2 # 计算滤波器中心点坐标
|
||||||
|
circles = [] # 存储已生成圆的列表
|
||||||
|
max_attempts = 1000 # 设置最大尝试次数,以避免无限循环
|
||||||
|
|
||||||
|
while len(circles) < num_circles and max_attempts > 0: # 循环,直到生成足够数量的不重叠圆
|
||||||
|
# 随机生成圆心位置,确保圆完全位于低频区域内
|
||||||
|
angle = random.uniform(0, 2 * np.pi)
|
||||||
|
r = random.uniform(0, cutoff_radius - circle_radius)
|
||||||
|
x = int(center_x + r * np.cos(angle))
|
||||||
|
y = int(center_y + r * np.sin(angle))
|
||||||
|
|
||||||
|
# 检查新生成的圆是否与已存在的圆重叠
|
||||||
|
overlapping = False
|
||||||
|
for cx, cy, cr in circles:
|
||||||
|
if np.sqrt((x - cx) ** 2 + (y - cy) ** 2) < (circle_radius + cr):
|
||||||
|
overlapping = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not overlapping: # 如果新圆不与任何已存在圆重叠,则添加到列表中
|
||||||
|
circles.append((x, y, circle_radius))
|
||||||
|
max_attempts -= 1
|
||||||
|
|
||||||
|
# 为每个生成的圆,在滤波器数组中设置对应区域的值为1
|
||||||
|
for (x, y, radius) in circles:
|
||||||
|
for i in range(-radius, radius + 1):
|
||||||
|
for j in range(-radius, radius + 1):
|
||||||
|
if np.sqrt(i ** 2 + j ** 2) <= radius:
|
||||||
|
filter[x + i, y + j] = 1 # 设置圆形区域的值为1
|
||||||
|
|
||||||
|
return filter
|
||||||
|
|
||||||
|
def generate_circles_in_frequency_domain(size, cutoff_radius, num_circles, circle_radius):
|
||||||
|
"""
|
||||||
|
生成指定数量的圆形,用于频域操作。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
size: 频域的大小(宽度和高度相同)。
|
||||||
|
cutoff_radius: 低频区域的半径,确保所有圆都在此区域内。
|
||||||
|
num_circles: 要生成的圆的数量。
|
||||||
|
circle_radius: 圆的半径。
|
||||||
|
|
||||||
|
返回值:
|
||||||
|
一个列表,包含每个圆的 (中心x坐标, 中心y坐标, 半径) 元组。
|
||||||
|
"""
|
||||||
|
center_x, center_y = size // 2, size // 2 # 计算频域中心点坐标
|
||||||
|
circles = [] # 存储已生成圆的列表
|
||||||
|
max_attempts = 1000 # 设置最大尝试次数,以避免无限循环
|
||||||
|
|
||||||
|
while len(circles) < num_circles and max_attempts > 0: # 循环,直到生成足够数量的不重叠圆
|
||||||
|
# 随机生成圆心位置,确保圆完全位于低频区域内
|
||||||
|
angle = random.uniform(0, 2 * np.pi)
|
||||||
|
r = random.uniform(0, cutoff_radius - circle_radius)
|
||||||
|
x = int(center_x + r * np.cos(angle))
|
||||||
|
y = int(center_y + r * np.sin(angle))
|
||||||
|
|
||||||
|
# 检查新生成的圆是否与已存在的圆重叠
|
||||||
|
overlapping = False
|
||||||
|
for cx, cy, cr in circles:
|
||||||
|
if np.sqrt((x - cx) ** 2 + (y - cy) ** 2) < (circle_radius + cr):
|
||||||
|
overlapping = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not overlapping: # 如果新圆不与任何已存在圆重叠,则添加到列表中
|
||||||
|
circles.append((x, y, circle_radius))
|
||||||
|
max_attempts -= 1
|
||||||
|
|
||||||
|
return circles
|
||||||
|
|
||||||
|
def draw_circles_on_frequency_domain(size, circles):
|
||||||
|
"""
|
||||||
|
在频域图中绘制圆形。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
size: 频域的大小(宽度和高度相同)。
|
||||||
|
circles: 包含每个圆的 (中心x坐标, 中心y坐标, 半径) 元组的列表。
|
||||||
|
|
||||||
|
返回值:
|
||||||
|
一个二维数组,表示频域图,其中圆形区域的值为1,其他区域的值为0。
|
||||||
|
"""
|
||||||
|
frequency_domain_image = np.zeros((size, size)) # 初始化频域图数组
|
||||||
|
|
||||||
|
# 遍历所有圆并在频域图中绘制它们
|
||||||
|
for (x, y, radius) in circles:
|
||||||
|
for i in range(-radius, radius + 1):
|
||||||
|
for j in range(-radius, radius + 1):
|
||||||
|
if i**2 + j**2 <= radius**2: # 判断点是否在圆内
|
||||||
|
# 检查绘制点是否在图像范围内
|
||||||
|
if 0 <= x + i < size and 0 <= y + j < size:
|
||||||
|
frequency_domain_image[x + i, y + j] = 1
|
||||||
|
|
||||||
|
return frequency_domain_image
|
||||||
|
|
||||||
|
def find_circles_in_filter(filter_array):
|
||||||
|
"""
|
||||||
|
从滤波器数组中识别圆形区域,提取每个圆的中心和半径。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
filter_array (ndarray): 一个二维数组,其中圆形区域的值为1,其他为0。
|
||||||
|
|
||||||
|
返回:
|
||||||
|
list: 每个圆的 (中心x坐标, 中心y坐标, 半径) 元组列表。
|
||||||
|
"""
|
||||||
|
labeled_image = label(filter_array) # 标记连通区域
|
||||||
|
regions = regionprops(labeled_image) # 提取区域属性
|
||||||
|
circles = []
|
||||||
|
for region in regions:
|
||||||
|
if region.area >= 5: # 排除太小的区域,假定它们不是我们要找的圆
|
||||||
|
radius = np.sqrt(region.area / np.pi) # 计算半径
|
||||||
|
circles.append((region.centroid[1], region.centroid[0], radius)) # x, y顺序要反转,因为centroid给出的是(row, col)
|
||||||
|
return circles
|
||||||
|
|
||||||
|
def distribute_points_on_circles(f_shifted, circles, num_points=240):
|
||||||
|
"""
|
||||||
|
将点均匀分布在每个圆周上。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
f_shifted: 平移处理的函数图像
|
||||||
|
circles (list of tuples): 每个元组包含一个圆的 (中心x坐标, 中心y坐标, 半径)
|
||||||
|
num_points (int): 每个圆上的点数量,默认为240
|
||||||
|
|
||||||
|
返回:
|
||||||
|
list: 每个圆的点坐标列表,每个元素为一个包含240个点的列表,每个点是(x, y)坐标的元组
|
||||||
|
"""
|
||||||
|
radians_per_step = 2 * np.pi / num_points # 计算每个步长的弧度值
|
||||||
|
print('弧度:', radians_per_step)
|
||||||
|
all_circle_points = [] # 存储所有圆的点坐标
|
||||||
|
|
||||||
|
for center_x, center_y, radius in circles:
|
||||||
|
# print('中心坐标:', center_x, center_y)
|
||||||
|
circle_points = [] # 存储单个圆的点坐标
|
||||||
|
for i in range(num_points):
|
||||||
|
theta = i * radians_per_step # 计算当前点的角度弧度
|
||||||
|
x = center_x + radius * np.cos(theta) # 极坐标转笛卡尔坐标(x)
|
||||||
|
y = center_y + radius * np.sin(theta) # 极坐标转笛卡尔坐标(y)
|
||||||
|
#通过笛卡尔坐标计算回角度
|
||||||
|
angle_radians = math.atan2(y - center_y, x - center_x)
|
||||||
|
angle_degrees = math.degrees(angle_radians)
|
||||||
|
#保留angle_degrees小数点后1位,四舍五入
|
||||||
|
angle_degrees = round(angle_degrees, 1)
|
||||||
|
#计算x,y坐标点的幅度
|
||||||
|
amplitude = np.abs(f_shifted[int(x), int(y)])
|
||||||
|
#计算x,y坐标点的相位
|
||||||
|
phase = np.angle(f_shifted[int(x), int(y)])
|
||||||
|
#将当前点的坐标,幅度以及相位打印出来
|
||||||
|
# print(f"x: {x}, y: {y}, angle: {angle_degrees}, amplitude: {amplitude}, phase: {phase}")
|
||||||
|
# 将当前点的坐标,幅度以及相位添加到列表
|
||||||
|
circle_points.append((int(x), int(y), angle_degrees, amplitude, phase)) # 添加当前点的坐标到列表
|
||||||
|
all_circle_points.append(circle_points) # 添加该圆的所有点坐标到主列表
|
||||||
|
#打印出circle_points中最大的幅度
|
||||||
|
# print(f"最大幅度:{max(circle_points, key=lambda x: x[3])[3]}")
|
||||||
|
|
||||||
|
# 将all_circle_points每个元素的点坐标根据amplitude进行降序排序
|
||||||
|
# for i in range(len(all_circle_points)):
|
||||||
|
# all_circle_points[i].sort(key=lambda x: x[3], reverse=True)
|
||||||
|
|
||||||
|
packed_circle_points = []
|
||||||
|
|
||||||
|
for circle_points in all_circle_points:
|
||||||
|
x, y, angles, amplitudes, phase = zip(*circle_points)
|
||||||
|
packed_circle_points.append((x, y, angles, amplitudes, phase))
|
||||||
|
|
||||||
|
return packed_circle_points
|
||||||
|
|
||||||
|
def degrees_to_radians(degrees):
|
||||||
|
"""
|
||||||
|
将角度转换为弧度。
|
||||||
|
|
||||||
|
参数:
|
||||||
|
degrees (float): 输入的角度值。
|
||||||
|
|
||||||
|
返回:
|
||||||
|
float: 转换后的弧度值。
|
||||||
|
"""
|
||||||
|
# 将角度乘以π/180,完成角度到弧度的转换
|
||||||
|
radians = degrees * (math.pi / 180)
|
||||||
|
return radians
|
||||||
|
|
||||||
|
# 将水印序列编码为二进制字符串
|
||||||
|
def encode_watermark_to_binary(watermark_sequence):
|
||||||
|
binary_sequence = []
|
||||||
|
for number in watermark_sequence:
|
||||||
|
# 初始化一个100位全为'0'的二进制字符串
|
||||||
|
binary_100_bit = ['0'] * 100
|
||||||
|
# 在数字对应的位置设置'1'
|
||||||
|
if 0 <= number < 100:
|
||||||
|
binary_100_bit[number-1] = '1'
|
||||||
|
# 连接这些位,形成一个100位的二进制字符串
|
||||||
|
binary_sequence.append(''.join(binary_100_bit))
|
||||||
|
return binary_sequence
|
||||||
|
|
||||||
|
#解析图片水印
|
||||||
|
def process_image_b_component(image_path, circles, watermarks):
|
||||||
|
num_points = 240
|
||||||
|
img = Image.open(image_path)
|
||||||
|
img = np.array(img)
|
||||||
|
# 将img缩放到 256*256
|
||||||
|
# img = cv2.resize(img, (339,339))
|
||||||
|
# img = cv2.resize(img, (500, 500))
|
||||||
|
img = cv2.resize(img, (255, 255))
|
||||||
|
b_channel = img[:, :, 2]
|
||||||
|
# 计算二维DFT并移位,使零频率分量在中心
|
||||||
|
f_transform = fft2(b_channel)
|
||||||
|
f_shifted = fftshift(f_transform)
|
||||||
|
radians_per_step = 2 * np.pi / num_points # 计算每个步长的弧度值
|
||||||
|
all_circle_points = [] # 存储所有圆的点坐标
|
||||||
|
|
||||||
|
for center_x, center_y, radius in circles:
|
||||||
|
# print('中心坐标:', center_x, center_y)
|
||||||
|
circle_points = [] # 存储单个圆的点坐标
|
||||||
|
for i in range(num_points):
|
||||||
|
theta = i * radians_per_step # 计算当前点的角度弧度
|
||||||
|
x = center_x + radius * np.cos(theta) # 极坐标转笛卡尔坐标(x)
|
||||||
|
y = center_y + radius * np.sin(theta) # 极坐标转笛卡尔坐标(y)
|
||||||
|
# 通过笛卡尔坐标计算回角度
|
||||||
|
angle_radians = math.atan2(y - center_y, x - center_x)
|
||||||
|
angle_degrees = math.degrees(angle_radians)
|
||||||
|
# 保留angle_degrees小数点后1位,四舍五入
|
||||||
|
angle_degrees = round(angle_degrees, 1)
|
||||||
|
# 计算x,y坐标点的幅度
|
||||||
|
amplitude = np.abs(f_shifted[int(x), int(y)])
|
||||||
|
# 计算x,y坐标点的相位
|
||||||
|
phase = np.angle(f_shifted[int(x), int(y)])
|
||||||
|
# 将当前点的坐标,幅度以及相位打印出来
|
||||||
|
print(f"x: {int(x)}, y: {int(y)}, angle: {angle_degrees}, amplitude: {amplitude}, phase: {phase}")
|
||||||
|
# 将当前点的坐标,幅度以及相位添加到列表
|
||||||
|
circle_points.append((int(x), int(y), angle_degrees, amplitude, phase)) # 添加当前点的坐标到列表
|
||||||
|
all_circle_points.append(circle_points) # 添加该圆的所有点坐标到主列表
|
||||||
|
|
||||||
|
watermark_result = []
|
||||||
|
#遍历all_circle_points
|
||||||
|
for i in range(len(all_circle_points)):
|
||||||
|
print(f"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 第{i + 1}个圆")
|
||||||
|
w = watermarks[i]
|
||||||
|
isOk = False
|
||||||
|
# 将all_circle_points每个元素的点坐标根据amplitude进行降序排序
|
||||||
|
all_circle_points[i].sort(key=lambda x: x[3], reverse=True)
|
||||||
|
# 打印all_circle_points[i]中每个元素
|
||||||
|
for j in range(16): # 只考虑每个圆的前四个最大幅度
|
||||||
|
point = all_circle_points[i][j]
|
||||||
|
print(f"幅度排名 {j + 1}: x: {point[0]}, y: {point[1]}, 角度: {point[2]}, 幅度: {point[3]}, 相位: {point[4]}")
|
||||||
|
# 处理角度,使其在0到360度范围内
|
||||||
|
adjusted_angle = point[2] if point[2] >= 0 else point[2] + 360
|
||||||
|
# 计算并打印当前角度是圆上的第几份
|
||||||
|
fraction_index = adjusted_angle / 1.5 + 1
|
||||||
|
if w == fraction_index:
|
||||||
|
print(f"水印匹配成功!角度:{adjusted_angle} , 编码:{fraction_index}")
|
||||||
|
# 将当前fraction_index添加到结果列表中,保留整数位
|
||||||
|
watermark_result.append(int(fraction_index))
|
||||||
|
isOk = True
|
||||||
|
break
|
||||||
|
if isOk == False:
|
||||||
|
watermark_result.append(0)
|
||||||
|
|
||||||
|
return watermark_result, img
|
||||||
|
|
||||||
|
def calculate_psnr(image1, image2):
|
||||||
|
mse = np.mean((image1 - image2) ** 2)
|
||||||
|
if mse == 0:
|
||||||
|
return float('inf')
|
||||||
|
max_pixel = 255.0
|
||||||
|
psnr = 20 * np.log10(max_pixel / np.sqrt(mse))
|
||||||
|
return psnr
|
||||||
|
|
||||||
|
def perspective_transform(img_path):
|
||||||
|
if not os.path.exists(img_path):
|
||||||
|
raise FileNotFoundError(f"Image file '{img_path}' not found.")
|
||||||
|
# 通过cv2加载图片
|
||||||
|
img = cv2.imread(img_path)
|
||||||
|
if img is None:
|
||||||
|
raise FileNotFoundError(f"Image file '{img_path}' not found or could not be read.")
|
||||||
|
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
|
||||||
|
# 复制图片
|
||||||
|
img_copy = img.copy()
|
||||||
|
# 将图片转灰度图
|
||||||
|
img_copy = cv2.cvtColor(img_copy, cv2.COLOR_BGR2GRAY)
|
||||||
|
# 黑白颜色反转
|
||||||
|
img_copy = cv2.bitwise_not(img_copy)
|
||||||
|
wechatqr = cv2.wechat_qrcode.WeChatQRCode("wechat_qrcode/detect.prototxt", "wechat_qrcode/detect.caffemodel",
|
||||||
|
"wechat_qrcode/sr.prototxt", "wechat_qrcode/sr.caffemodel")
|
||||||
|
res, points = wechatqr.detectAndDecode(img_copy)
|
||||||
|
# 在原图上标记二维码的角点
|
||||||
|
if len(res) > 0:
|
||||||
|
# for point in points[0]:
|
||||||
|
# cv2.circle(img, tuple(int(i) for i in point), 10, (255, 0, 0), -1) # 红色圆点,半径为10
|
||||||
|
point = points[0]
|
||||||
|
width = max(np.linalg.norm(point[0] - point[1]), np.linalg.norm(point[2] - point[3]))
|
||||||
|
height = max(np.linalg.norm(point[1] - point[2]), np.linalg.norm(point[3] - point[0]))
|
||||||
|
# 不添加边距
|
||||||
|
points_dst = np.array([[0, 0], [width, 0], [width, height], [0, height]], dtype=point.dtype)
|
||||||
|
# 生成变换矩阵
|
||||||
|
matrix = cv2.getPerspectiveTransform(point, points_dst)
|
||||||
|
# 应用透视变换,纠正图像
|
||||||
|
corrected_image = cv2.warpPerspective(img, matrix, (int(width), int(height)))
|
||||||
|
|
||||||
|
return corrected_image, img, res[0] # 返回校正后的图像和标记后的原图
|
||||||
|
|
||||||
|
return None, img, None # 如果没有检测到二维码,仅返回原图
|
||||||
|
|
||||||
|
|
||||||
|
def exec_image_result(img_path):
|
||||||
|
# 设置图像大小和截止频率半径
|
||||||
|
cutoff_radius = 80
|
||||||
|
# 在低通滤波器中添加8个随机圆形区域
|
||||||
|
circle_radius = 15 # 每个圆的半径
|
||||||
|
num_circles = 8 # 圆形数量
|
||||||
|
alpha = 1.5
|
||||||
|
# 加载图片
|
||||||
|
# img_path = 'qr8_1000.png'
|
||||||
|
# img = Image.open(img_path)
|
||||||
|
# img = np.array(img)
|
||||||
|
corrected_image, img, qr_res = perspective_transform(img_path)
|
||||||
|
# 复制一份原图
|
||||||
|
img_copy = corrected_image.copy()
|
||||||
|
# 获取img_copy的size
|
||||||
|
N, M, _ = img_copy.shape
|
||||||
|
print(f"img_copy size: {json.dumps(img_copy.shape)}")
|
||||||
|
# 提取B通道
|
||||||
|
b_channel = corrected_image[:, :, 2]
|
||||||
|
N, M = b_channel.shape
|
||||||
|
# 计算二维DFT并移位,使零频率分量在中心
|
||||||
|
f_transform = fft2(b_channel)
|
||||||
|
f_shifted = fftshift(f_transform)
|
||||||
|
# watermark_sequence = [77, 23, 51, 48, 44, 55, 22, 66] # 示例数字
|
||||||
|
watermark_sequence = [int(qr_res[i:i + 2]) for i in range(0, len(qr_res), 2)]
|
||||||
|
encoded_watermark = encode_watermark_to_binary(watermark_sequence)
|
||||||
|
# 展开所有的二进制编码成一个长字符串
|
||||||
|
flattened_encoded_watermark = ''.join(encoded_watermark)
|
||||||
|
print(flattened_encoded_watermark)
|
||||||
|
# 生成了指定数量的位于频域中的圆
|
||||||
|
circles = generate_circles_in_frequency_domain(b_channel.shape[0], cutoff_radius, num_circles, circle_radius)
|
||||||
|
# 绘制圆形
|
||||||
|
frequency_domain_image = draw_circles_on_frequency_domain(b_channel.shape[0], circles)
|
||||||
|
# 将circles转成 json
|
||||||
|
circles_json = json.dumps(circles)
|
||||||
|
print(circles_json)
|
||||||
|
# 获取当前时间
|
||||||
|
print(datetime.now())
|
||||||
|
# 保存数据
|
||||||
|
new_qr_data = qrcode_data.insert().values(key=json.dumps(watermark_sequence), circles=json.dumps(circles),
|
||||||
|
createdate=datetime.now())
|
||||||
|
connection.execute(new_qr_data)
|
||||||
|
connection.commit()
|
||||||
|
# connection.close()
|
||||||
|
distributed_points = distribute_points_on_circles(f_shifted, circles, 240)
|
||||||
|
# 总幅度
|
||||||
|
f_amplitudes = np.abs(f_shifted)
|
||||||
|
# 总相位
|
||||||
|
f_phase = np.angle(f_shifted)
|
||||||
|
for circle_index, (x, y, angles, amplitudes, phase) in enumerate(distributed_points):
|
||||||
|
# 根据指定的圆圈索引,从编码后的水印中获取对应的元素
|
||||||
|
cw = encoded_watermark[circle_index]
|
||||||
|
# 获取amplitudes的最大值
|
||||||
|
max_amplitude = max(amplitudes)
|
||||||
|
print(f"圆 {circle_index + 1} 的数据: 编码:{cw} ,最大幅度:{max_amplitude}")
|
||||||
|
# 这里我们可以访问每个圆的所有点的坐标、角度和幅度
|
||||||
|
for i in range(len(x)): # 假设每个圆有相同数量的点,例如240个
|
||||||
|
# print(f"点 {i + 1}: x = {int(x[i])}, y = {int(y[i])}, 角度 = {angles[i]}, 幅度 = {amplitudes[i]}, 相位 = {phase[i]}")
|
||||||
|
if i < len(cw): # 确保不会超出水印信息的长度
|
||||||
|
bit = cw[i] # 根据索引获取水印信息的当前位
|
||||||
|
if bit == '1':
|
||||||
|
original_amplitude = f_amplitudes[x[i], y[i]]
|
||||||
|
f_amplitudes[x[i], y[i]] = max_amplitude * alpha
|
||||||
|
f_amplitudes[N - x[i], M - y[i]] = max_amplitude * alpha
|
||||||
|
modified_amplitude = f_amplitudes[x[i], y[i]] # alpha是定义的强度因子
|
||||||
|
# print(f"点 {i + 1}: x = {int(x[i])}, y = {int(y[i])}, 角度 = {angles[i]}, 幅度 = {amplitudes[i]}, 相位 = {phase[i]}")
|
||||||
|
# print(f"原始幅度:{original_amplitude}")
|
||||||
|
# 打印嵌入水印信息后幅度
|
||||||
|
# print(f"嵌入水印信息后幅度: {modified_amplitude}")
|
||||||
|
else:
|
||||||
|
modified_amplitude = f_amplitudes[x[i], y[i]]
|
||||||
|
# 重新构造复数值并更新频域数据
|
||||||
|
# f_shifted[x[i], y[i]] = modified_amplitude * np.exp(1j * phase[i])
|
||||||
|
f_shifted = f_amplitudes * np.exp(1j * f_phase)
|
||||||
|
# 频域图像转换回空间域
|
||||||
|
img_lowpass_multi_circular = np.real(ifft2(ifftshift(f_shifted)))
|
||||||
|
b_channel = np.clip(img_lowpass_multi_circular, 0, 255).astype(np.uint16)
|
||||||
|
# 合并修改后的通道回到一个新的图像数组中
|
||||||
|
# merged_img = np.stack((r_channel, g_channel, b_channel), axis=-1)
|
||||||
|
corrected_image[:, :, 2] = b_channel
|
||||||
|
final_image = Image.fromarray(corrected_image)
|
||||||
|
# 添加边框
|
||||||
|
final_image_copy = final_image.copy()
|
||||||
|
border_size = 30
|
||||||
|
# border_color = (73, 116, 165)
|
||||||
|
# 设置border_color 为rgb 白色
|
||||||
|
border_color = (255, 255, 255)
|
||||||
|
border = (border_size, border_size, border_size, border_size) # (左, 上, 右, 下)
|
||||||
|
img_with_border = ImageOps.expand(final_image_copy, border=border, fill=border_color)
|
||||||
|
# 将merged_img保存到文件,文件是为当前时间的字符串
|
||||||
|
filename = f"{datetime.now().strftime('%Y%m%d%H%M%S')}.tiff"
|
||||||
|
# cv2.imwrite(filename, merged_img)
|
||||||
|
img_with_border.save(filename, format='TIFF')
|
||||||
|
# 显示结果
|
||||||
|
plt.figure(figsize=(12, 12))
|
||||||
|
plt.subplot(221)
|
||||||
|
plt.title("Original Image")
|
||||||
|
plt.imshow(img_copy, cmap='gray')
|
||||||
|
plt.subplot(222)
|
||||||
|
plt.title("Frequency Spectrum")
|
||||||
|
plt.imshow(np.log1p(np.abs(f_shifted)), cmap='gray')
|
||||||
|
plt.subplot(223)
|
||||||
|
plt.title("Multi Circular Lowpass Filter (50 Points per Circle)")
|
||||||
|
plt.imshow(frequency_domain_image, cmap='gray')
|
||||||
|
plt.subplot(224)
|
||||||
|
plt.title("Filtered Image (Multi Circular Low Frequencies, 50 Points per Circle)")
|
||||||
|
plt.imshow(final_image)
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.show()
|
||||||
|
return filename
|
||||||
|
|
||||||
|
|
||||||
|
def validate_qr(filename, watermark_sequence):
|
||||||
|
watermarks = [int(watermark_sequence[i:i + 2]) for i in range(0, len(watermark_sequence), 2)]
|
||||||
|
# 根据 key读取数据库圆形信息
|
||||||
|
key = json.dumps(watermarks)
|
||||||
|
circles = []
|
||||||
|
# 查询第一条数据
|
||||||
|
qr = qrcode_data.select().where(qrcode_data.c.key == key)
|
||||||
|
result = connection.execute(qr).first()
|
||||||
|
if result:
|
||||||
|
# 将json字符串转换为列表
|
||||||
|
circles = json.loads(result[1])
|
||||||
|
print(circles)
|
||||||
|
# 验证水印结果
|
||||||
|
result, img2 = process_image_b_component(filename, circles, watermarks)
|
||||||
|
print(result)
|
||||||
|
else:
|
||||||
|
print("未找到数据")
|
||||||
|
# psnr = calculate_psnr(img_copy, img2)
|
||||||
|
# print(f"PSNR: {psnr}")
|
||||||
|
# # PSNR > 40 dB:通常被认为是高质量图像
|
||||||
|
# # 30 dB < PSNR < 40 dB:图像质量是良好
|
||||||
|
# if psnr > 40:
|
||||||
|
# print("图像质量是高质量")
|
||||||
|
# elif 35 <= psnr < 40:
|
||||||
|
# print("图像质量是良好")
|
||||||
|
# else:
|
||||||
|
# print("图像质量是差")
|
||||||
|
|
||||||
|
# img_path = './temp/tmpb_1ffsve.png'
|
||||||
|
# exec_image_result(img_path)
|
||||||
|
|
||||||
|
img_path = "corrected_image.png"
|
||||||
|
qr = "9918314391322762"
|
||||||
|
validate_qr(img_path, qr)
|
||||||
|
|
||||||
|
# perspective_transform(img_path)
|
||||||
|
|
BIN
demo_border.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
fashion_mnist_model.h5
Normal file
50
fashion_test.py
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import numpy as np
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from tensorflow.keras.preprocessing import image
|
||||||
|
from tensorflow.keras.models import load_model
|
||||||
|
import tensorflow as tf
|
||||||
|
|
||||||
|
# # 加载Fashion-MNIST数据集
|
||||||
|
# fashion_mnist = tf.keras.datasets.fashion_mnist
|
||||||
|
# (X_train, y_train), (X_test, y_test) = fashion_mnist.load_data()
|
||||||
|
#
|
||||||
|
# # 数据预处理
|
||||||
|
# X_train = X_train / 255.0 # 将像素值缩放到0-1之间
|
||||||
|
# X_test = X_test / 255.0
|
||||||
|
#
|
||||||
|
# # 加载模型
|
||||||
|
# model = load_model('fashion_mnist_model.h5')
|
||||||
|
#
|
||||||
|
# # 评估模型
|
||||||
|
# loss, accuracy = model.evaluate(X_test, y_test)
|
||||||
|
# print(f'Test Loss: {loss}')
|
||||||
|
# print(f'Test Accuracy: {accuracy}')
|
||||||
|
|
||||||
|
|
||||||
|
# 图像文件路径
|
||||||
|
img_path = '运动鞋.png'
|
||||||
|
|
||||||
|
# 加载图像并调整大小
|
||||||
|
img = image.load_img(img_path, target_size=(28, 28), color_mode='grayscale')
|
||||||
|
|
||||||
|
# 将PIL图像转换为NumPy数组
|
||||||
|
img_array = image.img_to_array(img) / 255.0
|
||||||
|
|
||||||
|
# 添加批量维度
|
||||||
|
img_array = np.expand_dims(img_array, axis=0)
|
||||||
|
|
||||||
|
# 显示图像
|
||||||
|
plt.imshow(img_array[0, :, :, 0], cmap='gray')
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
# 打印图像数组形状
|
||||||
|
print(f'Image array shape: {img_array.shape}')
|
||||||
|
|
||||||
|
# 加载训练好的模型
|
||||||
|
model = load_model('fashion_mnist_model.h5')
|
||||||
|
|
||||||
|
# 进行预测
|
||||||
|
predictions = model.predict(img_array)
|
||||||
|
predicted_class = np.argmax(predictions, axis=1)
|
||||||
|
print(f'Predicted class: {predicted_class[0]}')
|
||||||
|
|
50
fashion_train.py
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import tensorflow as tf
|
||||||
|
from tensorflow.keras.models import Sequential
|
||||||
|
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense
|
||||||
|
|
||||||
|
# 加载Fashion-MNIST数据集
|
||||||
|
fashion_mnist = tf.keras.datasets.fashion_mnist
|
||||||
|
(X_train, y_train), (X_test, y_test) = fashion_mnist.load_data()
|
||||||
|
|
||||||
|
# 数据预处理
|
||||||
|
X_train = X_train / 255.0 # 将像素值缩放到0-1之间
|
||||||
|
X_test = X_test / 255.0
|
||||||
|
|
||||||
|
# 如果使用卷积神经网络(CNN),需要调整数据形状
|
||||||
|
X_train = X_train.reshape((X_train.shape[0], 28, 28, 1))
|
||||||
|
X_test = X_test.reshape((X_test.shape[0], 28, 28, 1))
|
||||||
|
|
||||||
|
# 标签数据保持不变
|
||||||
|
print(f'Training data shape: {X_train.shape}, Training labels shape: {y_train.shape}')
|
||||||
|
print(f'Test data shape: {X_test.shape}, Test labels shape: {y_test.shape}')
|
||||||
|
|
||||||
|
# 构建模型
|
||||||
|
model = Sequential([
|
||||||
|
Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),
|
||||||
|
MaxPooling2D((2, 2)),
|
||||||
|
Conv2D(64, (3, 3), activation='relu'),
|
||||||
|
MaxPooling2D((2, 2)),
|
||||||
|
Flatten(),
|
||||||
|
Dense(128, activation='relu'),
|
||||||
|
Dense(10, activation='softmax') # 输出层使用softmax进行10分类
|
||||||
|
])
|
||||||
|
|
||||||
|
# # 编译模型
|
||||||
|
# model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
|
||||||
|
#
|
||||||
|
# # 训练模型
|
||||||
|
# model.fit(X_train, y_train, epochs=15, batch_size=32, validation_split=0.2)
|
||||||
|
|
||||||
|
early_stopping = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=3)
|
||||||
|
lr_schedule = tf.keras.callbacks.LearningRateScheduler(lambda epoch: 1e-3 * 10**(epoch / 20))
|
||||||
|
|
||||||
|
model.compile(optimizer=tf.keras.optimizers.Adam(), loss='sparse_categorical_crossentropy', metrics=['accuracy'])
|
||||||
|
history = model.fit(X_train, y_train, epochs=100, batch_size=32, validation_split=0.2, callbacks=[early_stopping, lr_schedule])
|
||||||
|
|
||||||
|
|
||||||
|
# 评估模型
|
||||||
|
loss, accuracy = model.evaluate(X_test, y_test)
|
||||||
|
print(f'Test Loss: {loss}')
|
||||||
|
print(f'Test Accuracy: {accuracy}')
|
||||||
|
|
||||||
|
model.save('fashion_mnist_model.h5')
|
111
find_dominant_color.py
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
from sklearn.cluster import KMeans
|
||||||
|
from PIL import Image, ImageOps
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
# 定义函数,透视变换
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
def perspective_transform(img_path):
|
||||||
|
# 通过cv2加载图片
|
||||||
|
img = cv2.imread(img_path)
|
||||||
|
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
|
||||||
|
# 复制图片
|
||||||
|
img_copy = img.copy()
|
||||||
|
# 将图片转灰度图
|
||||||
|
img_copy = cv2.cvtColor(img_copy, cv2.COLOR_BGR2GRAY)
|
||||||
|
# 二值化
|
||||||
|
# 使用OTSU阈值算法将灰度图转换为二值图
|
||||||
|
_, binary_image = cv2.threshold(img_copy, 127, 255, cv2.THRESH_OTSU)
|
||||||
|
# inverted_binary_image = cv2.bitwise_not(binary_image)
|
||||||
|
# 黑白颜色反转
|
||||||
|
img_copy = cv2.bitwise_not(img_copy)
|
||||||
|
|
||||||
|
plt.title("Original Image")
|
||||||
|
plt.imshow(img_copy, cmap='gray')
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
wechatqr = cv2.wechat_qrcode.WeChatQRCode("wechat_qrcode/detect.prototxt", "wechat_qrcode/detect.caffemodel",
|
||||||
|
"wechat_qrcode/sr.prototxt", "wechat_qrcode/sr.caffemodel")
|
||||||
|
res, points = wechatqr.detectAndDecode(binary_image)
|
||||||
|
# 在原图上标记二维码的角点
|
||||||
|
if len(res) > 0:
|
||||||
|
print(res)
|
||||||
|
# for point in points[0]:
|
||||||
|
# cv2.circle(img, tuple(int(i) for i in point), 10, (255, 0, 0), -1) # 红色圆点,半径为10
|
||||||
|
|
||||||
|
point = points[0]
|
||||||
|
width = max(np.linalg.norm(point[0] - point[1]), np.linalg.norm(point[2] - point[3]))
|
||||||
|
height = max(np.linalg.norm(point[1] - point[2]), np.linalg.norm(point[3] - point[0]))
|
||||||
|
# 不添加边距
|
||||||
|
points_dst = np.array([[0, 0], [width, 0], [width, height], [0, height]], dtype=point.dtype)
|
||||||
|
# 生成变换矩阵
|
||||||
|
matrix = cv2.getPerspectiveTransform(point, points_dst)
|
||||||
|
# 应用透视变换,纠正图像
|
||||||
|
corrected_image = cv2.warpPerspective(img, matrix, (int(width), int(height)))
|
||||||
|
|
||||||
|
return corrected_image, img # 返回校正后的图像和标记后的原图
|
||||||
|
|
||||||
|
return None, img # 如果没有检测到二维码,仅返回原图
|
||||||
|
|
||||||
|
def perfect_reflectance_white_balance(img):
|
||||||
|
# 将图像从 BGR 转换到 LAB 色彩空间
|
||||||
|
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
|
||||||
|
|
||||||
|
# 分离 L, A, B 通道
|
||||||
|
l, a, b = cv2.split(lab)
|
||||||
|
|
||||||
|
# 寻找图像中的最亮区域(假设这些是白色区域)
|
||||||
|
max_lightness = np.max(l)
|
||||||
|
L_white = np.where(l == max_lightness)
|
||||||
|
|
||||||
|
# 计算这些区域在 A 和 B 通道上的平均值
|
||||||
|
a_white_avg = np.mean(a[L_white])
|
||||||
|
b_white_avg = np.mean(b[L_white])
|
||||||
|
|
||||||
|
# 适当调整 A 和 B 通道的平均值,避免过度调整
|
||||||
|
a_shift = (128 - a_white_avg) * 0.1 # 减少调整幅度
|
||||||
|
b_shift = (128 - b_white_avg) * 0.1 # 减少调整幅度
|
||||||
|
a = a.astype(np.float32) + a_shift
|
||||||
|
b = b.astype(np.float32) + b_shift
|
||||||
|
|
||||||
|
# 确保 a, b 范围在 0 到 255 之间,并转换回 uint8 类型
|
||||||
|
a = np.clip(a, 0, 255).astype(np.uint8)
|
||||||
|
b = np.clip(b, 0, 255).astype(np.uint8)
|
||||||
|
|
||||||
|
# 重新合成 LAB 图像并转换回 BGR 色彩空间
|
||||||
|
lab = cv2.merge([l, a, b])
|
||||||
|
corrected_image = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)
|
||||||
|
|
||||||
|
return corrected_image
|
||||||
|
|
||||||
|
|
||||||
|
corrected_image, img = perspective_transform("IMG_3606.png")
|
||||||
|
|
||||||
|
# 判断corrected_image不为空
|
||||||
|
if corrected_image is not None:
|
||||||
|
# 保存图片文件
|
||||||
|
corrected_image_bgr = cv2.cvtColor(corrected_image, cv2.COLOR_RGB2BGR)
|
||||||
|
cv2.imwrite("corrected_image.png", corrected_image_bgr)
|
||||||
|
# 通过 PIL 显示图片
|
||||||
|
plt.title("Original Image")
|
||||||
|
plt.imshow(corrected_image, cmap='gray')
|
||||||
|
plt.show()
|
||||||
|
else:
|
||||||
|
print("目标无法识别")
|
||||||
|
|
||||||
|
# # 读取图像
|
||||||
|
# image = cv2.imread('corrected_image.png')
|
||||||
|
# # 应用完美反射白平衡算法
|
||||||
|
# white_balanced_image = perfect_reflectance_white_balance(image)
|
||||||
|
#
|
||||||
|
# # 显示结果
|
||||||
|
# cv2.imshow('Original Image', image)
|
||||||
|
# cv2.imshow('White Balanced Image', white_balanced_image)
|
||||||
|
# cv2.waitKey(0)
|
||||||
|
# cv2.destroyAllWindows()
|
972
image_classification_dataset.ipynb
Normal file
90
main.py
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
# This is a sample Python script.
|
||||||
|
|
||||||
|
# Press ⌃R to execute it or replace it with your code.
|
||||||
|
# Press Double ⇧ to search everywhere for classes, files, tool windows, actions, and settings.
|
||||||
|
import numpy as np
|
||||||
|
from scipy.fft import fft2, fftshift
|
||||||
|
import cv2
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
def print_hi(name):
|
||||||
|
# Use a breakpoint in the code line below to debug your script.
|
||||||
|
print(f'Hi, {name}') # Press ⌘F8 to toggle the breakpoint.
|
||||||
|
|
||||||
|
|
||||||
|
def encode_watermark_to_binary(watermark_sequence):
|
||||||
|
binary_sequence = []
|
||||||
|
for number in watermark_sequence:
|
||||||
|
# 初始化一个100位全为'0'的二进制字符串
|
||||||
|
binary_100_bit = ['0'] * 100
|
||||||
|
# 在数字对应的位置设置'1'
|
||||||
|
if 0 <= number < 100:
|
||||||
|
binary_100_bit[number-1] = '1'
|
||||||
|
# 连接这些位,形成一个100位的二进制字符串
|
||||||
|
binary_sequence.append(''.join(binary_100_bit))
|
||||||
|
return binary_sequence
|
||||||
|
|
||||||
|
def process_image_b_component(image_path):
|
||||||
|
"""
|
||||||
|
处理图像的B通道,执行DFT并移动频谱。
|
||||||
|
|
||||||
|
:param image_path: 输入图像的路径。
|
||||||
|
:return: 移位后DFT的幅度矩阵。
|
||||||
|
"""
|
||||||
|
# 使用合适的库加载图像(例如,PIL, OpenCV)
|
||||||
|
# 这里我们会加载图像并提取B通道
|
||||||
|
# 作为演示,我们将创建一个假的256x256 B通道矩阵
|
||||||
|
|
||||||
|
#根据image_path加载图像
|
||||||
|
image = cv2.imread(image_path)
|
||||||
|
# 检查图像是否成功加载
|
||||||
|
if image is None:
|
||||||
|
raise ValueError("无法加载图像,请检查路径是否正确。")
|
||||||
|
|
||||||
|
# 确保图像的大小是256x256
|
||||||
|
image_resized = cv2.resize(image, (256, 256))
|
||||||
|
|
||||||
|
# 提取B通道
|
||||||
|
b_channel = image_resized[:, :, 0]
|
||||||
|
|
||||||
|
# 对B通道矩阵执行DFT
|
||||||
|
dft_result = fft2(b_channel)
|
||||||
|
|
||||||
|
# 将零频率分量移动到频谱的中心
|
||||||
|
dft_shifted = fftshift(dft_result)
|
||||||
|
|
||||||
|
# 获取移位后DFT的幅度
|
||||||
|
magnitude = np.abs(dft_shifted)
|
||||||
|
|
||||||
|
return magnitude
|
||||||
|
|
||||||
|
def decode_binary_to_watermark(binary_sequence):
|
||||||
|
"""
|
||||||
|
Decode the binary sequence back into the original array of numbers.
|
||||||
|
|
||||||
|
:param binary_sequence: A list of 100-bit strings representing the binary codes.
|
||||||
|
:return: The original array of numbers.
|
||||||
|
"""
|
||||||
|
original_numbers = []
|
||||||
|
for binary_code in binary_sequence:
|
||||||
|
if '1' in binary_code:
|
||||||
|
# Find the index of '1' and convert it back to the original number
|
||||||
|
position = binary_code.index('1') + 1 # Add 1 because the index starts at 0
|
||||||
|
original_number = position
|
||||||
|
original_numbers.append(original_number)
|
||||||
|
return original_numbers
|
||||||
|
|
||||||
|
# Press the green button in the gutter to run the script.
|
||||||
|
if __name__ == '__main__':
|
||||||
|
# print_hi('PyCharm')
|
||||||
|
watermark_sequence = [12, 34, 56, 44, 90, 55, 34, 56]
|
||||||
|
result = encode_watermark_to_binary(watermark_sequence)
|
||||||
|
print(result)
|
||||||
|
# # 打印编码后的二进制序列
|
||||||
|
# for binary in result:
|
||||||
|
# print(binary)
|
||||||
|
|
||||||
|
watermark_sequence = decode_binary_to_watermark(result)
|
||||||
|
print(watermark_sequence)
|
||||||
|
|
||||||
|
# See PyCharm help at https://www.jetbrains.com/help/pycharm/
|
BIN
my_images.pdf
Normal file
BIN
qr5_border.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
qr6_border.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
qr8_1000.png
Normal file
After Width: | Height: | Size: 163 KiB |
BIN
qr_code_detected.png
Normal file
After Width: | Height: | Size: 950 KiB |
BIN
res/20240510144434.png
Normal file
After Width: | Height: | Size: 90 KiB |
BIN
res/20240510144436.png
Normal file
After Width: | Height: | Size: 90 KiB |
BIN
res/20240510144438.png
Normal file
After Width: | Height: | Size: 89 KiB |
BIN
res/20240510144439.png
Normal file
After Width: | Height: | Size: 90 KiB |