OpenCV извлекает изображение методом LSB
Отказ от ответственности: это было частью домашнего задания, однако, оно уже было передано. Я просто ищу правильное решение для будущего ноу-хау.
Целью этой программы было использование библиотеки Python OpenCV для реализации изображения -> стеганография изображения (встраивание / извлечение изображений внутри других изображений). Это делается с двумя изображениями одинакового размера с использованием метода младшего значащего бита (LSB).
Программа позволяет пользователю выбирать количество битов, используемых для встраивания, поэтому при использовании 1 бита внедренное изображение почти не обнаруживается человеческим глазом, а с 7 вы можете четко разглядеть скрытое изображение.
Я правильно реализовал встраивание, просто взяв старшие биты (MSB) каждого байта RGB из секретного изображения и установив их в местах LSB изображения обложки.
Моя проблема заключается в извлечении секретного изображения после его встраивания. После запуска кода изображение, с которым я остаюсь, кажется только его синим представлением. Я не уверен, где я ошибся, но у меня есть ощущение, что это как-то связано с моей техникой манипулирования битами или использованием библиотеки OpenCV. Любая помощь с благодарностью, заранее спасибо!
Код для извлечения:
import cv2
import numpy
def extract(img1, bitsUsed):
print "Extracting..."
# Import image & get dimensions
img = cv2.imread(img1)
h = img.shape[0]
w = img.shape[1]
# Create new image to extract secret image
# Same dimensions, and rgb channel
secretImg = numpy.zeros((h,w,3), numpy.uint8)
x, y = 0, 0
# Loop thru each pixel
while x < w:
while y < h:
# Grab the LSB (based on bitsUsed from embedding)
lsb_B = img.item(y,x,0) & bitsUsed
lsb_G = img.item(y,x,1) & bitsUsed
lsb_R = img.item(y,x,2) & bitsUsed
# Place those bits into MSB positions on new img
secretImg.itemset((y,x,0), lsb_B << (8 - bitsUsed))
secretImg.itemset((y,x,0), lsb_G << (8 - bitsUsed))
secretImg.itemset((y,x,0), lsb_R << (8 - bitsUsed))
y += 1
y = 0
x += 1
cv2.imwrite("extractedImg.png", secretImg)
1 ответ
Нюффа это правильно. При извлечении, когда вы вставили только 1 бит, вы хотите использовать И с 0b00000001 (1), для 2 бит с 0b00000011 (3), для 3 бит с 0b00000111 (7) и т. Д. Обычно для k
встроенные биты, вы хотите маску 2**k - 1
,
Более того, cv2.imread()
сгенерирует пустой массив пикселей. Вместо прохождения каждого пикселя вы можете векторизовать свои вычисления. В общем, именно так может выглядеть ваш код.
import cv2
def embed(cover_file, secret_file, k):
cover = cv2.imread(cover_file)
secret = cv2.imread(secret_file)
mask = 256 - 2**k
stego = (cover & mask) | (secret >> (8 - k))
cv2.imwrite('stego.png', stego)
def extract(stego_file, k):
stego = cv2.imread(stego_file)
mask = 2**k - 1
output = (stego & mask) << (8 - k)
cv2.imwrite('extracted.png', output)