Spaces:
Sleeping
Sleeping
Add application file
Browse files- Dockerfile +13 -0
- api.py +143 -0
- requirements.txt +5 -0
Dockerfile
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM python:latest
|
2 |
+
|
3 |
+
WORKDIR /code
|
4 |
+
|
5 |
+
COPY ./requirements.txt /code/requirements.txt
|
6 |
+
|
7 |
+
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
|
8 |
+
|
9 |
+
COPY . .
|
10 |
+
|
11 |
+
EXPOSE 7860
|
12 |
+
|
13 |
+
CMD ["uvicorn", "app.api:app", "--host", "0.0.0.0", "--port", "7860"]
|
api.py
ADDED
@@ -0,0 +1,143 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Importing the required libraries
|
2 |
+
import cv2
|
3 |
+
from fastapi import FastAPI, File, UploadFile, HTTPException, Response, Form
|
4 |
+
from fastapi.middleware.cors import CORSMiddleware
|
5 |
+
import numpy as np
|
6 |
+
import json
|
7 |
+
import base64
|
8 |
+
|
9 |
+
app = FastAPI()
|
10 |
+
|
11 |
+
# Allowing CORS (Cross-Origin Resource Sharing)
|
12 |
+
app.add_middleware(
|
13 |
+
CORSMiddleware,
|
14 |
+
allow_origins=["*"],
|
15 |
+
allow_credentials=True,
|
16 |
+
allow_methods=["*"],
|
17 |
+
allow_headers=["*"],
|
18 |
+
)
|
19 |
+
|
20 |
+
# @app.on_event("startup")
|
21 |
+
# def save_openapi_json():
|
22 |
+
# openapi_data = app.openapi()
|
23 |
+
# with open("openapi.json", "w") as file:
|
24 |
+
# json.dump(openapi_data, file)
|
25 |
+
|
26 |
+
# Converting types to binary
|
27 |
+
def msg_to_bin(msg):
|
28 |
+
if type(msg) == str:
|
29 |
+
return ''.join([format(ord(i), "08b") for i in msg])
|
30 |
+
elif type(msg) == bytes or type(msg) == np.ndarray:
|
31 |
+
return [format(i, "08b") for i in msg]
|
32 |
+
elif type(msg) == int or type(msg) == np.uint8:
|
33 |
+
return format(msg, "08b")
|
34 |
+
else:
|
35 |
+
raise TypeError("Input type not supported")
|
36 |
+
|
37 |
+
# defining function to hide the secret message into the image
|
38 |
+
def hide_data(img, secret_msg):
|
39 |
+
# calculating the maximum bytes for encoding
|
40 |
+
nBytes = img.shape[0] * img.shape[1] * 3 // 8
|
41 |
+
print("Maximum Bytes for encoding:", nBytes)
|
42 |
+
# checking whether the number of bytes for encoding is less
|
43 |
+
# than the maximum bytes in the image
|
44 |
+
if len(secret_msg) > nBytes:
|
45 |
+
raise ValueError("Error encountered insufficient bytes, need bigger image or less data!!")
|
46 |
+
secret_msg += '#####' # we can utilize any string as the delimiter
|
47 |
+
dataIndex = 0
|
48 |
+
# converting the input data to binary format using the msg_to_bin() function
|
49 |
+
bin_secret_msg = msg_to_bin(secret_msg)
|
50 |
+
|
51 |
+
# finding the length of data that requires to be hidden
|
52 |
+
dataLen = len(bin_secret_msg)
|
53 |
+
for values in img:
|
54 |
+
for pixels in values:
|
55 |
+
# converting RGB values to binary format
|
56 |
+
r, g, b = msg_to_bin(pixels)
|
57 |
+
# modifying the LSB only if there is data remaining to store
|
58 |
+
if dataIndex < dataLen:
|
59 |
+
# hiding the data into LSB of Red pixel
|
60 |
+
pixels[0] = int(r[:-1] + bin_secret_msg[dataIndex], 2)
|
61 |
+
dataIndex += 1
|
62 |
+
if dataIndex < dataLen:
|
63 |
+
# hiding the data into LSB of Green pixel
|
64 |
+
pixels[1] = int(g[:-1] + bin_secret_msg[dataIndex], 2)
|
65 |
+
dataIndex += 1
|
66 |
+
if dataIndex < dataLen:
|
67 |
+
# hiding the data into LSB of Blue pixel
|
68 |
+
pixels[2] = int(b[:-1] + bin_secret_msg[dataIndex], 2)
|
69 |
+
dataIndex += 1
|
70 |
+
# if data is encoded, break out the loop
|
71 |
+
if dataIndex >= dataLen:
|
72 |
+
break
|
73 |
+
|
74 |
+
return img
|
75 |
+
|
76 |
+
def show_data(img):
|
77 |
+
bin_data = ""
|
78 |
+
for values in img:
|
79 |
+
for pixels in values:
|
80 |
+
# converting the Red, Green, Blue values into binary format
|
81 |
+
r, g, b = msg_to_bin(pixels)
|
82 |
+
# data extraction from the LSB of Red pixel
|
83 |
+
bin_data += r[-1]
|
84 |
+
# data extraction from the LSB of Green pixel
|
85 |
+
bin_data += g[-1]
|
86 |
+
# data extraction from the LSB of Blue pixel
|
87 |
+
bin_data += b[-1]
|
88 |
+
# split by 8-Bits
|
89 |
+
allBytes = [bin_data[i: i + 8] for i in range(0, len(bin_data), 8)]
|
90 |
+
# converting from bits to characters
|
91 |
+
decodedData = ""
|
92 |
+
for bytes in allBytes:
|
93 |
+
decodedData += chr(int(bytes, 2))
|
94 |
+
# checking if we have reached the delimiter which is "#####"
|
95 |
+
if decodedData[-5:] == "#####":
|
96 |
+
break
|
97 |
+
# print(decodedData)
|
98 |
+
# removing the delimiter to display the actual hidden message
|
99 |
+
return decodedData[:-5]
|
100 |
+
|
101 |
+
@app.get("/")
|
102 |
+
async def root():
|
103 |
+
return {"message": "Server is alive"}
|
104 |
+
|
105 |
+
@app.post("/hide_message")
|
106 |
+
async def hide_message(image: UploadFile = File(...), secret_msg: str = Form(...)):
|
107 |
+
try:
|
108 |
+
# Read image using OpenCV
|
109 |
+
content = await image.read()
|
110 |
+
nparr = np.frombuffer(content, np.uint8)
|
111 |
+
img = cv2.imdecode(nparr, cv2.IMREAD_UNCHANGED)
|
112 |
+
|
113 |
+
# Hide the secret message in the image
|
114 |
+
encoded_image = hide_data(img, secret_msg)
|
115 |
+
|
116 |
+
# Convert the image to bytes
|
117 |
+
_, encoded_image_data = cv2.imencode(".png", encoded_image)
|
118 |
+
encoded_image_bytes = encoded_image_data.tobytes()
|
119 |
+
|
120 |
+
# Encode the image bytes to base64
|
121 |
+
encoded_image_base64 = base64.b64encode(encoded_image_bytes).decode()
|
122 |
+
|
123 |
+
# Return the base64 encoded image
|
124 |
+
return {"base64_image": encoded_image_base64}
|
125 |
+
except Exception as e:
|
126 |
+
raise HTTPException(status_code=500, detail=str(e))
|
127 |
+
|
128 |
+
|
129 |
+
# API endpoint to retrieve the secret message from an image
|
130 |
+
@app.post("/retrieve_message")
|
131 |
+
async def retrieve_message(image: UploadFile = File(...)):
|
132 |
+
try:
|
133 |
+
# Read image using OpenCV
|
134 |
+
content = await image.read()
|
135 |
+
nparr = np.frombuffer(content, np.uint8)
|
136 |
+
img = cv2.imdecode(nparr, cv2.IMREAD_UNCHANGED)
|
137 |
+
|
138 |
+
# Retrieve the hidden message from the image
|
139 |
+
decoded_message = show_data(img)
|
140 |
+
|
141 |
+
return {"decoded_message": decoded_message}
|
142 |
+
except Exception as e:
|
143 |
+
raise HTTPException(status_code=500, detail=str(e))
|
requirements.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
opencv-python-headless
|
2 |
+
fastapi
|
3 |
+
python-multipart
|
4 |
+
numpy
|
5 |
+
uvicorn
|