This commit is contained in:
Admin 2024-06-25 14:15:07 +08:00
commit 47f231bb21
155 changed files with 61637 additions and 0 deletions

8
.idea/.gitignore vendored Normal file
View 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

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

View 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
View 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
View 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
View 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
View 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>

View 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
0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
20240507153436.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

BIN
20240507153436.png.zip Normal file

Binary file not shown.

BIN
20240507173217.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 KiB

BIN
20240507173217.png.zip Normal file

Binary file not shown.

BIN
20240517105758.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
20240517105800.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
20240517105802.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
20240517105803.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
20240517105805.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
20240517105806.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
20240517105808.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

BIN
20240517105810.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
20240517105812.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
20240517105813.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
20240517105815.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
20240517105816.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

BIN
20240517105818.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
20240517105820.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
20240517105821.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
20240517105823.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
20240517105824.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
20240517105826.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
20240517105828.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

BIN
20240517105829.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
20240517115712.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
20240517115712.tiff Normal file

Binary file not shown.

BIN
20240517135556.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
20240517135556.tiff Normal file

Binary file not shown.

BIN
20240517140142.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
20240517140142.tiff Normal file

Binary file not shown.

BIN
20240517140325.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
20240517140325.tiff Normal file

Binary file not shown.

BIN
20240517140418.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
20240517140418.tiff Normal file

Binary file not shown.

BIN
Bag.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

BIN
Dress.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

BIN
IMG_3584.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

BIN
IMG_3585.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

BIN
IMG_3592.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 MiB

BIN
IMG_3593.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 MiB

BIN
IMG_3594.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

BIN
IMG_3596.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
IMG_3599.tiff Normal file

Binary file not shown.

BIN
IMG_3604.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 748 KiB

BIN
IMG_3606.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 KiB

BIN
IMG_3684.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

BIN
Shirt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
Sneaker.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

BIN
Sneaker.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 943 KiB

BIN
Trouser.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
WechatIMG7309.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 MiB

64
check-1.py Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

BIN
corrected_image.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

BIN
corrected_image.tiff Normal file

Binary file not shown.

139
creare_pdf.py Normal file
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

BIN
demo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

490
demo.py Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
fashion_mnist_model.h5 Normal file

Binary file not shown.

50
fashion_test.py Normal file
View 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
View 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
View 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()

File diff suppressed because one or more lines are too long

BIN
img.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 MiB

90
main.py Normal file
View 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

Binary file not shown.

BIN
qr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
qr1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
qr2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
qr3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
qr4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
qr5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
qr5_border.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
qr6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
qr6_border.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
qr7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
qr8_1000.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

BIN
qr_code_detected.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 950 KiB

BIN
qr_v1.pdf Normal file

Binary file not shown.

BIN
qr_v2.pdf Normal file

Binary file not shown.

BIN
qr_wx.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
qr_wz.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 998 KiB

BIN
res/20240510144434.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

BIN
res/20240510144436.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

BIN
res/20240510144438.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

BIN
res/20240510144439.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Some files were not shown because too many files have changed in this diff Show More