def reed_solomon_decode(txt: typing.Union[bytes, str, bytearray], number_repair_symbols: int = 2) -> bytes: global rscodec, number_r_symbols if rscodec is None or number_r_symbols != number_repair_symbols: rscodec = RSCodec(number_repair_symbols) number_r_symbols = number_repair_symbols return bytes(rscodec.decode(txt))
def test_prim_fcr_basic(self): nn = 30 kk = 18 tt = nn - kk rs = RSCodec(tt, fcr=120, prim=0x187) hexencmsg = '00faa123555555c000000354064432c02800fe97c434e1ff5365' \ 'cf8fafe4' strf = str if sys.version_info[0] >= 3 else unicode encmsg = bytearray.fromhex(strf(hexencmsg)) decmsg = encmsg[:kk] tem = rs.encode(decmsg) self.assertEqual(encmsg, tem, msg="encoded does not match expected") tdm = rs.decode(tem) self.assertEqual(tdm, decmsg, msg="decoded does not match original") tem1 = bytearray(tem) # clone a copy # encoding and decoding intact message seem OK, so test errors numerrs = tt >> 1 # inject tt/2 errors (expected to recover fully) for i in sample(range(nn), numerrs): # inject errors in random places tem1[i] ^= 0xff # flip all 8 bits tdm = rs.decode(tem1) self.assertEqual(tdm, decmsg, msg="decoded with errors does not match original") tem1 = bytearray(tem) # clone another copy numerrs += 1 # inject tt/2 + 1 errors (expected to fail and detect it) for i in sample(range(nn), numerrs): # inject errors in random places tem1[i] ^= 0xff # flip all 8 bits # if this fails, it means excessive errors not detected self.assertRaises(ReedSolomonError, rs.decode, tem1)
def __init__(self, callsign): self.sequenceId = 0 callsignLen = 6 if len(callsign) > 6 else len(callsign) self.callsign = bytes( callsign[:callsignLen].upper() + ' ' * (6 - len(callsign)), 'utf-8') self.rs = RSCodec(16)
def rsdecode(rscode, msglen): ''' msg:rs二进制码 ''' ecc = RSCodec(96) length = len(rscode) padmsglen = (msglen // 7 + 1) * 7 rslen = padmsglen + 96 * 8 temp = [] for i in range(0, padmsglen, 7): temp.append(int(rscode[i:i + 7], 2)) for i in range(padmsglen, rslen, 8): temp.append(int(rscode[i:i + 8], 2)) temp = bytearray(temp) try: rscode = ecc.decode(temp) rscode = ''.join(format(x, '08b') for x in rscode) finally: if len(rscode) == length: print('too many bits errors!') return rscode[:msglen] else: temp = '' for i in range(0, padmsglen // 7 * 8, 8): temp += rscode[i + 1:i + 8] return temp[:msglen]
def generate(n, k=12, mnemonic=Mnemonic("english")): """Generate a mnemonic phrase with the specified level of error correction. Phrases include t=(n-k) "error correcting" words, allowing the correction of up to t invalid words in a phrase, and up to floor(t/2) words that are wrong, but still valid BIP-39 words. Arguments: n (int): Total number of words in the phrase. k (int): Number of words chosen at random. mnemonic (Mnemonic): Instance of Mnemonic to use. """ ok, error = validate_n_k(n, k) if not ok: raise ValueError(error) coder = RSCodec(nsize=n, nsym=(n-k), c_exp=BIP39_SYMBOL_SIZE) for i in itertools.count(): bits = random_bits(k*BIP39_SYMBOL_SIZE) symbols = bits_to_symbols(bits, BIP39_SYMBOL_SIZE) coded = coder.encode(symbols) phrase = symbols_to_mnemonic(coded, mnemonic) if not mnemonic.check(phrase): continue return phrase
def listen_linux(frame_rate=44100, interval=0.1): mic = alsaaudio.PCM(alsaaudio.PCM_CAPTURE, alsaaudio.PCM_NORMAL, device="default") mic.setchannels(1) mic.setrate(44100) mic.setformat(alsaaudio.PCM_FORMAT_S16_LE) num_frames = int(round((interval / 2) * frame_rate)) mic.setperiodsize(num_frames) print("start...") in_packet = False packet = [] while True: l, data = mic.read() if not l: continue chunk = np.fromstring(data, dtype=np.int16) dom = dominant(frame_rate, chunk) if in_packet and match(dom, HANDSHAKE_END_HZ): byte_stream = extract_packet(packet) try: byte_stream = RSCodec(FEC_BYTES).decode(byte_stream) byte_stream = byte_stream.decode("utf-8") #print(byte_stream) if "201502091" in byte_stream: # remove studentId new_byteStream = byte_stream.replace('201502091 ', '').strip() display(new_byteStream) #print(new_byteStream) #print(type(new_byteStream) new_byteStream = RSCodec(FEC_BYTES).encode(new_byteStream) #print(type(new_byteStream))--> bytearray play(new_byteStream) # call main function #new_byteStream = new_byteStream.encode("utf-8") #new_byteStream = RSCodec(FEC_BYTES).encode(new_byteStream) except ReedSolomonError as e: pass #print("{}: {}".format(e, byte_stream)) packet = [] in_packet = False elif in_packet: packet.append(dom) elif match(dom, HANDSHAKE_START_HZ): in_packet = True
def __init__(self, max_payload, ec_bytes, seed = 1895746671, mother = "bior3.1", sparsity = 0.7): self.mother = mother self.sparsity = sparsity self.rscodec = RSCodec(ec_bytes) self.max_payload = max_payload self.total_bits = (max_payload + ec_bytes) * 8 self.seed = seed
def __init__(self): self.rsc = RSCodec(10) # default to be 10 self.delimiter = b"|:|:|" # type bytes self.checksum = 0 # type String self.length = str(0) self.seqNo = 0 self.msg = 0
def extract_packet(freqs): # listen_linux 함수에서 쓰임 freqs = freqs[::2] ## 2개씩 끊어서 가져옴 bit_chunks = [int(round((f - START_HZ) / STEP_HZ)) for f in freqs] bit_chunks = [c for c in bit_chunks[1:] if 0 <= c < (2**BITS)] byte_stream = bytearray(decode_bitchunks(BITS, bit_chunks)) try: byte_stream = RSCodec(FEC_BYTES).decode(byte_stream) byte_stream = byte_stream.decode("utf-8") if "201502049" in byte_stream: except_byte_stream = byte_stream.replace("201502049", "") del freqs[20:-8] with noalsaerr(): p = pyaudio.PyAudio() stream = p.open(format=pyaudio.paFloat32, channels=1, rate=44100, output=True) for freq in freqs: samples = (np.sin(2 * np.pi * np.arange(44100 * 0.4) * freq / 44100)).astype(np.float32) stream.write(samples) stream.stop_stream() stream.close() p.terminate() except ReedSolomonError as e: #pass print("{}: {}".format(e, byte_stream)) return except_byte_stream
def test_prim_fcr_long(self): nn = 48 kk = 34 tt = nn - kk rs = RSCodec(tt, fcr=120, prim=0x187) hexencmsg = '08faa123555555c000000354064432c0280e1b4d090cfc04887400' \ '000003500000000e1985ff9c6b33066ca9f43d12e8' strf = str if sys.version_info[0] >= 3 else unicode encmsg = bytearray.fromhex(strf(hexencmsg)) decmsg = encmsg[:kk] tem = rs.encode(decmsg) self.assertEqual(encmsg, tem, msg="encoded does not match expected") tdm = rs.decode(tem) self.assertEqual(tdm, decmsg, msg="decoded does not match original") tem1 = bytearray(tem) numerrs = tt >> 1 for i in sample(range(nn), numerrs): tem1[i] ^= 0xff tdm = rs.decode(tem1) self.assertEqual(tdm, decmsg, msg="decoded with errors does not match original") tem1 = bytearray(tem) numerrs += 1 for i in sample(range(nn), numerrs): tem1[i] ^= 0xff self.assertRaises(ReedSolomonError, rs.decode, tem1)
def decode(quart_coded_data): quart_coded_data = quart_coded_data[4:-4:] binary_coded_data = '' for byte in quart_coded_data: if byte == '0': binary_coded_data += '00' elif byte == '1': binary_coded_data += '01' elif byte == '2': binary_coded_data += '10' elif byte == '3': binary_coded_data += '11' else: raise ValueError coded_data = [] for bit_chunk in range(0, len(binary_coded_data), 8): chunk_data = '' for bit_ind in range(8): chunk_data += binary_coded_data[bit_chunk + bit_ind] value = int(chunk_data, 2) coded_data.append(value) coded_data = bytes(coded_data) rsc = RSCodec(10) decoded_data = rsc.decode(coded_data)[0].decode() return decoded_data
def decodeWithReedSolo(encodedata): if len(encodedata) > 255: return b'', False, 255 # print(encodedata) # if len(encodedata) > 255: # c = math.ceil(len(encodedata) / 2) # print(c) # if c > 255: # c = 255 # byte2, check2, err2 = decodeWithReedSolo(encodedata[c:]) # byte1, check1, err1 = decodeWithReedSolo(encodedata[:c]) # if (check2[0] and check1[0]): # print(check2) # return byte1 + byte2, check1, err1 + err2 # else: # ecc_len = math.ceil(len(encodedata) / (1+errorPercent) * errorPercent) # return b'', False, ecc_len // 2 + 1 ecc_len = math.ceil(len(encodedata) / (1 + errorPercent) * errorPercent) # print(ecc_len) rsc = RSCodec(math.ceil(ecc_len)) check = rsc.check(encodedata) try: decoded_msg, decoded_msgecc, errata_pos = rsc.decode(encodedata) check = rsc.check(decoded_msgecc) return decoded_msg, check, len(errata_pos) except: return b'', check, ecc_len // 2 + 1
def encodeWithReedSolo(bytedata, length=0): if len(bytedata) > 182 or length > 256: return b'' ecc_len = 0 if length == 0: # if len(bytedata) > 182: # c = math.ceil(len(bytedata) / 2) # if c > 182: # c = 182 # return encodeWithReedSolo(bytedata[:c]) + encodeWithReedSolo(bytedata[c:]) ecc_len = math.ceil(len(bytedata) * errorPercent) else: # if length > 255: # c = math.ceil(length / 2) # print(c) # if c > 255: # c = 255 # return encodeWithReedSolo(bytedata[:c]) + encodeWithReedSolo(bytedata[c:]) print('use length ' + str(length)) ecc_len = math.ceil(int(length) / (1 + errorPercent) * errorPercent) bytedata += os.urandom(math.floor(length - ecc_len - len(bytedata))) print('error: ' + str(ecc_len)) print('random: ' + str(math.floor(length - ecc_len - len(bytedata)))) print('data: ' + str(len(bytedata))) rsc = RSCodec(ecc_len) encodedata = rsc.encode(bytedata) print('ENCODED') print(len(encodedata)) return encodedata
def __init__(self, PACKEGE_SIZE, NUMBER_OF_ERRORS, packeg_q, size_results=10, packeg_n=16): # create logger self.logger = logging.getLogger('add_reed') self.logger.setLevel(logging.INFO) self.PACKEGE_SIZE = PACKEGE_SIZE self.NUMBER_OF_ERRORS = NUMBER_OF_ERRORS self.rsc = RSCodec(NUMBER_OF_ERRORS) #give information about how much the reed will be able to fix #maxerrors, maxerasures = self.rsc.maxerrata(verbose=True) #self.logger.info("This codec can correct up to"+maxerrors+" errors and"+ maxerasures+" erasures independently") self.packeg_q = packeg_q self.packeg_proportion = { "normal": packeg_n, "reed5": self.check_len_reed(NUMBER_OF_ERRORS, packeg_n) } self.reed5_q = queue.Queue(maxsize=size_results) super(AddReed5, self).__init__()
def recover(phrase, k=12, mnemonic=Mnemonic("english")): """Attempts to recover the original mnemonic phrase from a mnemonic phrase with errors. Infers the value of n from the number of words in the phrase. If words are missing or unknown, include an arbitrary character in its place. (e.g. '_') Arguments: phrase (str): Mnemonic phrase with errors to fix. k (int): Number of words chosen at random. mnemonic (Mnemonic): Instance of Mnemonic to use. """ symbols = mnemonic_to_symbols(phrase, mnemonic) ok, error = validate_n_k(len(symbols), k) if not ok: raise ValueError(error) coder = RSCodec(nsize=len(symbols), nsym=(len(symbols)-k), c_exp=BIP39_SYMBOL_SIZE) erasures = [i for i, s in enumerate(symbols) if s < 0] recovered, _, _ = coder.decode(symbols, erase_pos=erasures) coded = coder.encode(recovered) phrase = symbols_to_mnemonic(coded, mnemonic) if not mnemonic.check(phrase): raise ValueError("error-corrected phrase does not have a valid checksum") return phrase
def __init__(self, packet_seq_num, telemetry_packet_type, current_batch_num, current_chunk_num, chunk): self.rsc = RSCodec(16) # 16 ecc symbols self.chunk = chunk packet_data = self._create_chunk_packet_data(telemetry_packet_type, current_batch_num, current_chunk_num, chunk) super().__init__(packet_seq_num, packet_data)
def main(): for i in range(0, 256): postit = np.tile(np.uint8([255]), (postit_height, postit_width, 1)) #draw location dot for count in range(0, 8): location_dot_array = [1] + [ 0 for j in range(0, location_dot_num - 1) ] for j in range(0, len(location_dot_array) - 2): if count & 2**j != 0: location_dot_array[j + 1] = 1 if count < 3: draw_location_dot(postit, location_dot_array, horizon_x_buffer + count * horizon_space, horizon_y_buffer, True) elif count < 6: draw_location_dot( postit, location_dot_array, horizon_x_buffer + (count - 3) * horizon_space, postit_height - horizon_y_buffer - location_height, True) elif count == 6: draw_location_dot(postit, location_dot_array, horizon_y_buffer, postit_height / 2 - location_width / 2, False) elif count == 7: draw_location_dot( postit, location_dot_array, postit_width - horizon_y_buffer - location_height, postit_height / 2 - location_width / 2, False) #need reed solomon rs = RSCodec(14) rs_result = rs.encode([i]) #make bit array bit_array_all = [] for number in rs_result: #print number bit_array = [0 for j in range(0, bit_num)] for j in range(0, bit_num - 1): if number & 2**j != 0: bit_array[j] = 1 bit_array[bit_num - 1] = bit_array[0] bit_array_all.append(bit_array) #draw bit array draw_all_bit(bit_array_all, postit) #outer rectangle cv2.rectangle(postit, (0, 0), (postit_width - 1, postit_height - 1), 0, 1) #cv2.imshow("result", postit) #cv2.waitKey(0) filename = "./datas/postit/postit" + str(i) + ".jpg" cv2.imwrite(filename, postit)
def remove_reed5(self, s1,missing_pack_list): rsc = RSCodec(self.NUMBER_OF_ERRORS) try: s2 = rsc.decode(s1,erase_pos=missing_pack_list) return (s2[0]) except: return (None)
def test_correction(self): rs = RSCodec(10) msg = bytearray("hello world " * 10, "utf8") enc = rs.encode(msg) self.assertEqual(rs.decode(enc), msg) for i in [27, -3, -9, 7, 0]: enc[i] = 99 self.assertEqual(rs.decode(enc), msg) enc[82] = 99 self.assertRaises(ReedSolomonError, rs.decode, enc)
def test_long(self): rs = RSCodec(10) msg = bytearray("a" * 10000, "utf8") enc = rs.encode(msg) dec = rs.decode(enc) self.assertEqual(dec, msg) enc[177] = 99 enc[2212] = 88 dec2 = rs.decode(enc) self.assertEqual(dec2, msg)
def decode(compressed, coding): #correct errors if coding!=0 if(coding): rs = RSCodec(coding) compressed = rs.decode(compressed) #decompress the bytes in_bytes = zlib.decompress(compressed) #decode the text in bytes string = in_bytes.decode("utf-8") return string
def decode(msg): for i in range(1,81): try: rs=RSCodec(80-i) x=rs.decode(msg) return x except: pass return "UNREADABLE"
def encode(string, coding): #encode the text in bytes in_bytes = string.encode("utf-8") #compress the bytes compressed = zlib.compress(in_bytes, 9) # if coding!=0, add error correcting code if(coding): rs = RSCodec(coding) compressed = rs.encode(compressed) return compressed
def decode(self, text) -> typing.Tuple[int, bytes]: norepair_symbols: bytes = xor_mask(struct.unpack("<I", text[:4])[0]) text = text[4:] if self.rscodec is None: self.rscodec = RSCodec(int(norepair_symbols)) decoded = self.rscodec.decode(text) i: int = struct.unpack("<I", decoded[:4])[0] i: int = xor_mask(i) data: bytes = decoded[4:] return i, data
class RSCode: """ Reed-Solomon encoder and decoder """ def __init__(self, num_ec=None): """ Create R.S. Code with given number of EC symbols. corrects num_ec / 2 errors. """ self.num_ec = num_ec or config.RS_NUM_EC self.coder = RSCodec(self.num_ec) def encode(self, bitarr): output = [] bitarr_bytes = _bitarr2bytes(bitarr, 8, 8) encoded = self.coder.encode(bitarr_bytes) output = _bytes2bitarr(encoded) return output def decode(self, bitarr, starts_to_try=10): if not bitarr: print('warning: empty block received') return # sometimes we have extra bytes at the beginning, fix that by bruteforcing for offs in range(starts_to_try): try: if len(bitarr) % 8: # cut off unaligned bitarr_trim = bitarr[:-len(bitarr) % 8] else: bitarr_trim = bitarr if config.DEBUG: import os.path decoded = bitarr_trim[:] if os.path.exists('_actual_message.npy'): if offs: print('reed-solomon offset =', offs) actual = np.load('_actual_message.npy') while len(decoded) > len(actual): decoded.pop() while len(decoded) < len(actual): decoded.append(0) Y = np.array(decoded) X = np.array(actual) bitwise_errs = np.sum(np.abs(Y - X)) X = X.reshape(-1, 8) Y = Y.reshape(-1, 8) errs = np.sum(np.any(X != Y, axis=1)) #print(X) #print(Y) print('bit errors', bitwise_errs, '=', bitwise_errs / len(decoded)) print('byte errors', errs, '=', errs / (len(decoded) // 8)) bitarr_bytes = _bitarr2bytes(bitarr_trim, None) decoded = self.coder.decode(bitarr_bytes)[0] output = _bytes2bitarr(decoded) return _unpad(output, 8) except: bitarr = bitarr[8:] raise Exception('FATAL: reed-solomon decoding failed')
def listen_linux(frame_rate=44100, interval=0.1): mic = alsaaudio.PCM(alsaaudio.PCM_CAPTURE, alsaaudio.PCM_NORMAL, device="default") mic.setchannels(1) mic.setrate(44100) mic.setformat(alsaaudio.PCM_FORMAT_S16_LE) num_frames = int(round((interval / 2) * frame_rate)) mic.setperiodsize(num_frames) print("start...") in_packet = False packet = [] while True: l, data = mic.read() if not l: continue chunk = np.fromstring(data, dtype=np.int16) dom = dominant(frame_rate, chunk) if in_packet and match(dom, HANDSHAKE_END_HZ): bit_chunks, byte_stream = extract_packet(packet) try: byte_stream = RSCodec(FEC_BYTES).decode(byte_stream) byte_stream = byte_stream.decode("utf-8") try: index = byte_stream.index("201502007") except: index = -1 if (index > -1): stream = bit_chunks[0:index * 2] + bit_chunks[index * 2 + 18:-8] rs = [] for target in RSCodec(4).encode(byte_stream[0:index] + byte_stream[index + 9:])[-4:]: rs.append(int(target / 16)) rs.append(target & 15) stream = [12] + stream + rs + [20] make_sounds(stream) display(byte_stream) except ReedSolomonError as e: pass # print("{}: {}".format(e, byte_stream)) packet = [] in_packet = False elif in_packet: packet.append(dom) elif match(dom, HANDSHAKE_START_HZ): in_packet = True
def listen_linux(frame_rate=44100, interval=0.1): mic = alsaaudio.PCM(alsaaudio.PCM_CAPTURE, alsaaudio.PCM_NORMAL, device="default") mic.setchannels(1) mic.setrate(44100) mic.setformat(alsaaudio.PCM_FORMAT_S16_LE) num_frames = int(round((interval / 2) * frame_rate)) mic.setperiodsize(num_frames) print("start...") in_packet = False packet = [] while True: l, data = mic.read() if not l: continue chunk = np.fromstring(data, dtype=np.int16) dom = dominant(frame_rate, chunk) if in_packet and match(dom, HANDSHAKE_END_HZ): byte_stream = extract_packet(packet) #print("packet: ",packet) try: byte_stream = RSCodec(FEC_BYTES).decode(byte_stream) byte_stream_test = byte_stream.decode("utf-8") if '201402455' in byte_stream_test: byte_stream = re.sub(b'201402455',b''0,byte_stream) byte_stream = RSCodec(FEC_BYTES).encode(byte_stream) temp_stream = [] temp_stream.append(HANDSHAKE_START_HZ) temp_stream.append(HANDSHAKE_START_HZ) for i in range(len(byte_stream)): temp_stream.append(((byte_stream[i] >> 4)*STEP_HZ)+START_HZ) temp_stream.append(((byte_stream[i] & 0xf)*STEP_HZ)+START_HZ) temp_stream.append(HANDSHAKE_END_HZ) temp_stream.append(HANDSHAKE_END_HZ) p = pyaudio.PyAudio() stream = p.open(format=pyaudio.paFloat32, channels=1, rate =44100, output = True) duration = 0.5 # for i in range(len(n:ewbyte_stream)): samples = (np.sin(2*np.pi*np.arange(44100*duration)*(temp_stream[i]/44100))).astype(np.float32) stream.write(samples) stream.stop_stream() stream.close() p.terminate() else: print("don't have my_number")
def __init__(self, max_payload, ec_bytes, seed=1910819922, mother="haar"): self.mother = mother self.rscodec = RSCodec(ec_bytes) self.max_payload = max_payload self.total_bits = (max_payload + ec_bytes) * 8 rand = Random(seed) chunk_size = 50000 self.seq0 = numpy.array( [int(rand.random() > 0.7) for _ in range(chunk_size)]) self.seq1 = numpy.array(self.seq0[::-1])
class PublicCode: def __init__(self): self.n = 78 * 768 self.inner_code = RSCodec(78 - 32) self.outer_code = ReedMuller(6) def encode(self, msg): return self.outer_code.encode(self.inner_code.encode(msg)) def decode(self, msg): return self.inner_code.decode(self.outer_code.decode(msg))
def _unhead(self, hh: bytes): _rrs = RSCodec() try: hd = _rrs.decode(hh)[0] except: print('broken header') hd = hh[:-10] if hd[:5] != b'FsTeg': raise Exception('Unknown header type') ll = 1 + int.from_bytes(hd[8:12], 'little') * \ self.block_size // _rsc_block return ll
def trame(data, conf): out = bytearray([conf["trame"]["startbyte"]]) for i, val in enumerate(data): # Concaténation des valeurs des capteurs out += struct.pack(str("!"+ conf["sensors"][i]), *val) out += bytearray([functools.reduce(operator.xor, out)]) rs = RSCodec(conf["trame"]["ecc"]["length"]) out = rs.encode(out) return out
def listen_linux(frame_rate=44100, interval=0.1): mic = alsaaudio.PCM(alsaaudio.PCM_CAPTURE, alsaaudio.PCM_NORMAL) mic.setchannels(1) mic.setrate(44100) mic.setformat(alsaaudio.PCM_FORMAT_S16_LE) num_frames = int(round((interval / 2) * frame_rate)) mic.setperiodsize(num_frames) print("start...") in_packet = False ch_next = False packet = [] while True: l, data = mic.read() if not l: continue chunk = np.fromstring( data, dtype=np.int16) #convert voice to bit with each tone dom = dominant(frame_rate, chunk) #Fourier Transfer: back to original #print(dom); #print(dom) if in_packet and ch_next and dom < 1000: #abs(HAND - dom) packet.pop() byte_stream = extract_packet(packet) print("original code", byte_stream) try: # check errors byte_stream = RSCodec(FEC_BYTES).decode( byte_stream) # reed solo byte_stream = byte_stream.decode("utf-8") display(byte_stream) display("") except ReedSolomonError as e: print("{}: {}".format(e, byte_stream)) packet = [] in_packet = False ch_next = False elif in_packet: packet.append(dom) if match(dom, HANDSHAKE_END_HZ): ch_next = True elif match(dom, HANDSHAKE_START_HZ): in_packet = True
def listen_linux(frame_rate=44100, interval=0.1): HANDSHAKE_START_HZ = 8192 HANDSHAKE_END_HZ = HANDSHAKE_START_HZ + 512 mic = alsaaudio.PCM(alsaaudio.PCM_CAPTURE, alsaaudio.PCM_NORMAL) mic.setchannels(1) mic.setrate(44100) mic.setformat(alsaaudio.PCM_FORMAT_S16_LE) #2 num_frames = int(round((interval / 2) * frame_rate)) mic.setperiodsize(num_frames) print("start...") in_packet = False packet = [] coeff = 0 while True: l, data = mic.read() #nyquist 2*bandwidth*log2(L) if not l: continue chunk = np.fromstring(data, dtype=np.int16) dom = dominant(frame_rate, chunk) #print(dom) #print(HANDSHAKE_START_HZ) #print(dom) if in_packet and match(dom, HANDSHAKE_END_HZ): #print(packet) byte_stream = extract_packet(packet) #print(byte_stream) print("original code", byte_stream) try: byte_stream = RSCodec(FEC_BYTES).decode(byte_stream) byte_stream = byte_stream.decode("utf-8") display(byte_stream) display("") except ReedSolomonError as e: print("{}: {}".format(e, byte_stream)) packet = [] in_packet = False elif in_packet: packet.append(dom) elif match(dom, HANDSHAKE_START_HZ): in_packet = True
def __init__(self, max_payload, ec_bytes, seed = 1910819922, mother = "haar"): self.mother = mother self.rscodec = RSCodec(ec_bytes) self.max_payload = max_payload self.total_bits = (max_payload + ec_bytes) * 8 rand = Random(seed) chunk_size = 50000 self.seq0 = numpy.array([int(rand.random() > 0.7) for _ in range(chunk_size)]) self.seq1 = numpy.array(self.seq0[::-1])
def demodul(data,size): assert(size % 7 != 0) ''' ret = bytearray(size) ndata = bytearray(data) idx = (-7) % size for i in range(size - 1,-1,-1): for j in range(8): ret[i] = (ret[i] << 1) | (ndata[idx] & 1) ndata[idx] = (ndata[idx] >> 1) idx = (idx - 7) % size ''' rsc = RSCodec(size - 43) try: ret = rsc.decode(data) except: ret = None return ret
def __init__(self, max_payload, ec_bytes, seed = 1910819922, mother = "haar"): self.mother = mother self.rscodec = RSCodec(ec_bytes) self.max_payload = max_payload self.total_bits = (max_payload + ec_bytes) * 8 rand = Random(seed) chunk_size = 3000 while True: self.seq0 = numpy.array([int(rand.random() > 0.8) for _ in range(chunk_size)]) self.seq1 = numpy.array([int(rand.random() > 0.75) for _ in range(chunk_size)]) corr, _ = pearsonr(self.seq0, self.seq1) if corr < self.EPSILON: break
def slimdecode(frame, config): rs = RSCodec(config["trame"]["ecc"]["length"]) frame = rs.decode(frame) cs = frame.pop() if cs != functools.reduce(operator.xor, frame): print("Checksum failed") return False frame.pop(0) # Stripping start byte out = [] for fmt in config["sensors"]: l = struct.calcsize(fmt) val, = struct.unpack("!" + fmt, frame[:l]) frame = frame[l:] out.append(val) print(len(frame)) return out
def __init__(self, msg_bytes, ec_bytes, seed, mother = "haar"): self.mother = mother self.rscodec = RSCodec(ec_bytes) self.msg_bytes = msg_bytes self.total_bits = (msg_bytes + ec_bytes) * 8 rand = Random(seed) #self.mask = [rand.randint(0,255) for _ in range(msg_bytes + ec_bytes)] self.mask = [0] * (msg_bytes + ec_bytes) chunk_size = 256*512 // self.total_bits espilon = 0.0001 while True: self.seq0 = numpy.array([int(rand.random() > 0.75) for _ in range(chunk_size)]) self.seq1 = numpy.array([int(rand.random() > 0.7) for _ in range(chunk_size)]) corr, _ = pearsonr(self.seq0, self.seq1) if abs(corr) < espilon: break
class Watermarker(object): def __init__(self, msg_bytes, ec_bytes, seed, mother = "haar"): self.mother = mother self.rscodec = RSCodec(ec_bytes) self.msg_bytes = msg_bytes self.total_bits = (msg_bytes + ec_bytes) * 8 rand = Random(seed) #self.mask = [rand.randint(0,255) for _ in range(msg_bytes + ec_bytes)] self.mask = [0] * (msg_bytes + ec_bytes) chunk_size = 256*512 // self.total_bits espilon = 0.0001 while True: self.seq0 = numpy.array([int(rand.random() > 0.75) for _ in range(chunk_size)]) self.seq1 = numpy.array([int(rand.random() > 0.7) for _ in range(chunk_size)]) corr, _ = pearsonr(self.seq0, self.seq1) if abs(corr) < espilon: break def _embed(self, img, payload, k): cA, (cH, cV, cD) = dwt2(img, self.mother) w, h = cH.shape cH2 = cH.reshape(cH.size) cV2 = cV.reshape(cV.size) chunk_size = cH2.size // (self.total_bits // 2) assert chunk_size >= self.seq0.size for i, bit in enumerate(iterbits(payload)): dst = (cH2, cV2)[i % 2] seq = (self.seq0, self.seq1)[bit] dst[(i//2)*chunk_size:(i//2)*chunk_size + seq.size] += k * seq return idwt2((cA, (cH2.reshape(w, h), cV2.reshape(w, h), cD)), self.mother)[:img.shape[0],:img.shape[1]] def embed(self, img, payload, k = 10): if len(payload) > self.msg_bytes: raise ValueError("payload too long") if isinstance(payload, str): payload = bytearray(payload) payload.extend([0] * (self.msg_bytes - len(payload))) encoded = self.rscodec.encode(payload) masked = [v ^ m for v, m in zip(encoded, self.mask)] if len(img.shape) == 2: return self._embed(img, masked, k) elif len(img.shape) == 3: res = numpy.zeros(img.shape) for i in range(img.shape[2]): layer = self._embed(img[:,:,i], masked, k) res[:,:,i] = layer return res else: raise TypeError("image must be a 2d or 3d array") def _extract(self, img): cA, (cH, cV, cD) = dwt2(img, self.mother) w, h = cH.shape cH2 = cH.reshape(cH.size) cV2 = cV.reshape(cV.size) chunk_size = cH2.size // (self.total_bits // 2) maskiter = iter(self.mask) payload = bytearray() byte = 0 for i in range(self.total_bits): src = (cH2, cV2)[i % 2] chunk = src[(i//2)*chunk_size:(i//2)*chunk_size + self.seq0.size] corr0, _ = pearsonr(chunk, self.seq0) corr1, _ = pearsonr(chunk, self.seq1) bit = int(corr1 > corr0) byte = bit | (byte << 1) if i % 8 == 7: payload.append(byte ^ maskiter.next()) byte = 0 print repr(payload) return self.rscodec.decode(payload) def extract(self, img): if len(img.shape) == 2: return self._extract(img) elif len(img.shape) == 3: for i in range(img.shape[2]): try: return self._extract(img[:,:,i]) except ReedSolomonError: pass return self._extract(mean(img, 2)) else: raise TypeError("image must be a 2d or 3d array")
class Watermarker(object): EPSILON = 0.001 def __init__(self, max_payload, ec_bytes, seed = 1910819922, mother = "haar"): self.mother = mother self.rscodec = RSCodec(ec_bytes) self.max_payload = max_payload self.total_bits = (max_payload + ec_bytes) * 8 rand = Random(seed) chunk_size = 50000 self.seq0 = numpy.array([int(rand.random() > 0.7) for _ in range(chunk_size)]) self.seq1 = numpy.array(self.seq0[::-1]) def _interleave(self, cH, cV, cD): arr = numpy.zeros(cH.size + cV.size + cD.size) sources = [cH.reshape(cH.size), cV.reshape(cV.size), cD.reshape(cD.size)] for i in range(arr.size): src = sources[i % 3] j = i // 3 if j >= src.size: arr = arr[:i] break arr[i] = src[j] return arr def _deinterleave(self, arr, cH, cV, cD): cH2 = numpy.zeros(cH.size) cV2 = numpy.zeros(cV.size) cD2 = numpy.zeros(cD.size) destinations = [cH2, cV2, cD2] for i in range(arr.size): destinations[i % 3][i // 3] = arr[i] return cH2.reshape(cH.shape), cV2.reshape(cV.shape), cD2.reshape(cD.shape) def _embed(self, img, payload, k): cA, (cH, cV, cD) = dwt2(img, self.mother) arr = self._interleave(cH, cV, cD) chunk_size = arr.size // self.total_bits sequence_of = (self.seq0[:chunk_size], self.seq1[:chunk_size]) for i, bit in enumerate(iterbits(payload)): seq = sequence_of[bit] arr[i * chunk_size: i * chunk_size + seq.size] += k * seq w, h = img.shape cH2, cV2, cD2 = self._deinterleave(arr, cH, cV, cD) return idwt2((cA, (cH2, cV2, cD2)), self.mother)[:w,:h] def embed(self, img, payload, k): if len(payload) > self.max_payload: raise ValueError("payload too long") padded = bytearray(payload) + b"\x00" * (self.max_payload - len(payload)) encoded = self.rscodec.encode(padded) if img.ndim == 2: return self._embed(img, encoded, k) elif img.ndim == 3: output = numpy.zeros(img.shape) for i in range(img.shape[2]): output[:,:,i] = self._embed(img[:,:,i], encoded, k) return output else: raise TypeError("img must be a 2d or 3d array") def _extract(self, img): cA, (cH, cV, cD) = dwt2(img, self.mother) arr = self._interleave(cH, cV, cD) chunk_size = arr.size // self.total_bits seq0 = self.seq0[:chunk_size] seq1 = self.seq1[:chunk_size] byte = 0 output = bytearray() for i in range(self.total_bits): chunk = arr[i * chunk_size: i * chunk_size + seq0.size] corr0, _ = pearsonr(chunk, seq0) corr1, _ = pearsonr(chunk, seq1) bit = int(corr1 > corr0) byte = (byte << 1) | bit if i % 8 == 7: output.append(byte) byte = 0 return output def _try_decode(self, payload): try: out = self.rscodec.decode(payload) except ReedSolomonError: #print "!!", repr(payload) try: rpayload = bytearray(b ^ 255 for b in payload) out = self.rscodec.decode(rpayload) except ReedSolomonError: #print "!!", repr(rpayload) out = None return out def extract(self, img): if img.ndim == 2: return self._try_decode(self._extract(img)) elif img.ndim == 3: for i in range(img.shape[2]): out = self._try_decode(self._extract(img[:,:,i])) if out is not None: return out return self._try_decode(self._extract(mean(img, 2))) else: raise TypeError("img must be a 2d or 3d array")
class Watermarker(object): EPSILON = 0.001 def __init__(self, max_payload, ec_bytes, seed = 1910819922, mother = "haar"): self.mother = mother self.rscodec = RSCodec(ec_bytes) self.max_payload = max_payload self.total_bits = (max_payload + ec_bytes) * 8 self.seed = seed def _embed(self, img, payload, k): rand = Random(self.seed) cA, (cH, cV, cD) = dwt2(img, self.mother) cD2 = cD.reshape(cD.size) for bit in iterbits(payload): seq = numpy.array([int(rand.random() > 0.95) for _ in range(cD2.size)]) if bit: cD2 += k * seq return idwt2((cA, (cH, cV, cD2.reshape(cD.shape))), self.mother)[:img.shape[0],:img.shape[1]] def embed(self, img, payload, k): if len(payload) > self.max_payload: raise ValueError("payload too long") payload = bytearray(payload) + "\x00" * (self.max_payload - len(payload)) encoded = self.rscodec.encode(payload) if len(img.shape) == 2: return self._embed(img, encoded, k) elif len(img.shape) == 3: output = numpy.zeros(img.shape) for i in range(img.shape[2]): output[:,:,i] = self._embed(img[:,:,i], encoded, k) return output else: raise TypeError("img must be a 2d or 3d array") def _extract(self, img): rand = Random(self.seed) cA, (cH, cV, cD) = dwt2(img, self.mother) cD2 = cD.reshape(cD.size) byte = 0 output = bytearray() for i in range(self.total_bits): seq = numpy.array([int(rand.random() > 0.95) for _ in range(cD2.size)]) corr, _ = pearsonr(cD2, seq) bit = int(corr > 0.1) byte = (byte << 1) | bit if i % 8 == 7: output.append(byte) byte = 0 print repr(output) return output def extract(self, img): if len(img.shape) == 2: return self.rscodec.decode(self._extract(img)) elif len(img.shape) == 3: for i in range(img.shape[2]): try: return self.rscodec.decode(self._extract(img[:,:,i])) except ReedSolomonError: pass return self.rscodec.decode(self._extract(mean(img, 2))) else: raise TypeError("img must be a 2d or 3d array")
class Watermarker(object): EPSILON = 0.001 def __init__(self, max_payload, ec_bytes, seed = 1910819922, mother = "haar"): self.mother = mother self.rscodec = RSCodec(ec_bytes) self.max_payload = max_payload self.total_bits = (max_payload + ec_bytes) * 8 rand = Random(seed) chunk_size = 50000 self.seq0 = numpy.array([int(rand.random() > 0.7) for _ in range(chunk_size)]) self.seq1 = numpy.array(self.seq0[::-1]) #while True: # self.seq0 = numpy.array([int(rand.random() > 0.8) for _ in range(chunk_size)]) # self.seq1 = numpy.array([int(rand.random() > 0.75) for _ in range(chunk_size)]) # corr, _ = pearsonr(self.seq0, self.seq1) # if corr < self.EPSILON: # break def _embed(self, img, payload, k): cA, (cH, cV, cD) = dwt2(img, self.mother) cH2 = cH.reshape(cH.size) cV2 = cV.reshape(cV.size) cD2 = cD.reshape(cD.size) assert cH2.shape == cV2.shape == cD2.shape chunk_size = (cH2.size * 3) // (self.total_bits) sequence_of = (self.seq0[:chunk_size], self.seq1[:chunk_size]) buffers = (cH2, cV2, cD2) for i, bit in enumerate(iterbits(payload)): seq = sequence_of[bit] target = buffers[i % 3] offset = (i//3) * chunk_size target[offset:offset + seq.size] += k * seq w, h = img.shape return idwt2((cA, (cH2.reshape(cH.shape), cV2.reshape(cV.shape), cD2.reshape(cD.shape))), self.mother)[:w,:h] def embed(self, img, payload, k): if len(payload) > self.max_payload: raise ValueError("payload too long") padded = bytearray(payload) + b"\x00" * (self.max_payload - len(payload)) encoded = self.rscodec.encode(padded) if len(img.shape) == 2: return self._embed(img, encoded, k) elif len(img.shape) == 3: output = numpy.zeros(img.shape) for i in range(img.shape[2]): output[:,:,i] = self._embed(img[:,:,i], encoded, k) return output else: raise TypeError("img must be a 2d or 3d array") def _extract(self, img): cA, (cH, cV, cD) = dwt2(img, self.mother) cH2 = cH.reshape(cH.size) cV2 = cV.reshape(cV.size) cD2 = cD.reshape(cD.size) assert cH2.shape == cV2.shape == cD2.shape buffers = (cH2, cV2, cD2) chunk_size = (cH2.size * 3) // (self.total_bits) seq0 = self.seq0[:chunk_size] seq1 = self.seq1[:chunk_size] byte = 0 output = bytearray() for i in range(self.total_bits): target = buffers[i % 3] offset = (i//3) * chunk_size chunk = target[offset : offset + seq0.size] corr0, _ = pearsonr(chunk, seq0) corr1, _ = pearsonr(chunk, seq1) bit = int(corr1 > corr0) byte = (byte << 1) | bit if i % 8 == 7: output.append(byte) byte = 0 #print repr(output) return output def extract(self, img): if len(img.shape) == 2: return self.rscodec.decode(self._extract(img)) elif len(img.shape) == 3: for i in range(img.shape[2]): try: return self.rscodec.decode(self._extract(img[:,:,i])) except ReedSolomonError: pass return self.rscodec.decode(self._extract(mean(img, 2))) else: raise TypeError("img must be a 2d or 3d array")
def __init__(self, max_payload, ec_bytes, seed = 1910819922, mother = "haar"): self.mother = mother self.rscodec = RSCodec(ec_bytes) self.max_payload = max_payload self.total_bits = (max_payload + ec_bytes) * 8 self.seed = seed
def test_simple(self): rs = RSCodec(10) msg = bytearray("hello world " * 10, "utf8") enc = rs.encode(msg) dec = rs.decode(enc) self.assertEqual(dec, msg)
def decode_rs(fragments): fragment_lengths = ", ".join(["{}:{}".format(i, len(f)) for i,f in enumerate(fragments)]) p.pr("RS decode {} fragments of length {}".format( len(fragments), fragment_lengths)) #for f in fragments: # p.hexpr(" ZE FRAGMENT", f); # Transpose fragments to get an RS block rs_block = "".join("".join(f) for f in zip(*fragments)) # chunks before protection have size chunk_size # protection adds 48 bytes # The tuples here are (data, parity) #p.hexpr(" ZE RS BLOCK", "".join(rs_block)) num_chunks = len(rs_block) / chunk_size data_size = chunk_size + 48 af_packet_size = num_chunks * chunk_size p.pr("AF Packet size {}".format(af_packet_size)) # Cut the block into list of (data, protection) tuples rs_chunks = [ (rs_block[i*data_size:i*data_size + chunk_size], rs_block[i*data_size + chunk_size:(i+1)*data_size]) for i in range(num_chunks)] chunk_lengths = ", ".join(["{}:{}+{}".format(i, len(c[0]), len(c[1])) for i,c in enumerate(rs_chunks)]) p.pr("{} chunks of length {}".format(num_chunks, chunk_lengths)) #for c in rs_chunks: # p.hexpr(" ZE CHUNK DATA", c[0]); # p.hexpr(" ZE CHUNK PROT", c[1]); if verify_protection: rs_codec = RSCodec(48, fcr=1) protection_ok = True for chunk, protection in rs_chunks: #p.pr(" Protection") #p.hexpr(" OF ZE CHUNK DATA", chunk); bchunk = bytearray(chunk) padbytes = 255-(48 + len(chunk)) bchunk = bchunk + bytearray(0 for i in range(padbytes)) recalc_protection = rs_codec.encode(bchunk)[-48:] if protection != recalc_protection: p.pr(" PROTECTION ERROR") p.hexpr(" data", chunk) p.hexpr(" orig", protection) p.hexpr(" calc", recalc_protection) protection_ok = False else: p.pr(" PROTECTION OK") if protection_ok: p.pr("Protection check: OK") afpacket = "".join(data for (data, protection) in rs_chunks) #p.hexpr(" ZE AF PACKET", afpacket) if zeropad: return decode_af(afpacket[0:-zeropad]) else: return decode_af(afpacket)
class Watermarker(object): def __init__(self, max_payload, ec_bytes, seed = 1895746671, mother = "bior3.1", sparsity = 0.7): self.mother = mother self.sparsity = sparsity self.rscodec = RSCodec(ec_bytes) self.max_payload = max_payload self.total_bits = (max_payload + ec_bytes) * 8 self.seed = seed ''' def _interleave(self, cH, cV, cD): vec = numpy.zeros(cH.size + cV.size + cD.size) rcH = cH.ravel() lH = cH.size rcV = cV.ravel() lV = cH.size + cV.size rcD = cD.ravel() rand = Random(self.seed) indexes = range(vec.size) rand.shuffle(indexes) for i, j in enumerate(indexes): vec[i] = rcD[j - lV] if j >= lV else (rcV[j - lH] if j >= lH else rcH[j]) return vec def _deinterleave(self, vec, cH, cV, cD): cH2 = numpy.zeros(cH.shape) rcH = cH2.ravel() lH = cH.size cV2 = numpy.zeros(cV.shape) rcV = cV2.ravel() lV = cH.size + cV.size cD2 = numpy.zeros(cD.shape) rcD = cD2.ravel() rand = Random(self.seed) indexes = range(vec.size) rand.shuffle(indexes) for i, v in enumerate(vec): j = indexes[i] if j >= lV: rcD[j -lV] = v elif j >= lH: rcV[j - lH] = v else: rcH[j] = v return cH2, cV2, cD2 ''' @classmethod def _interleave(cls, cH, cV, cD): vec = numpy.zeros(cH.size + cV.size + cD.size, dtype = float) vec[0::3] = cH.ravel() vec[1::3] = cV.ravel() vec[2::3] = cD.ravel() return vec @classmethod def _deinterleave(cls, vec, cH, cV, cD): return vec[0::3].reshape(cH.shape), vec[1::3].reshape(cV.shape), vec[2::3].reshape(cD.shape) def _generate_sequences(self, chunk_size): rand = Random(self.seed) seq0 = numpy.array([int(rand.random() >= self.sparsity) for _ in range(chunk_size)]) seq1 = seq0[::-1] return seq0, seq1 def _embed(self, img, payload, k): cA, (cH, cV, cD) = dwt2(img.astype(float), self.mother) vec = self._interleave(cH, cV, cD) chunk_size = vec.size // self.total_bits sequences = self._generate_sequences(chunk_size) for i, bit in enumerate(iterbits(payload)): offset = i * chunk_size vec[offset : offset + chunk_size] += k * sequences[bit] #vec[i:self.total_bits*chunk_size:self.total_bits] += k * sequences[bit] w, h = img.shape cH2, cV2, cD2 = self._deinterleave(vec, cH, cV, cD) return idwt2((cA, (cH2, cV2, cD2)), self.mother)[:w,:h] def embed(self, img, payload, k = 6, tv_denoising_weight = 4, rescale = True): if len(payload) > self.max_payload: raise ValueError("payload too long") padded = bytearray(payload) + b"\x00" * (self.max_payload - len(payload)) encoded = self.rscodec.encode(padded) if img.ndim == 2: output = self._embed(img, encoded, k) elif img.ndim == 3: output = numpy.zeros(img.shape, dtype=float) for i in range(img.shape[2]): output[:,:,i] = self._embed(img[:,:,i], encoded, k) #y, cb, cr = rgb_to_ycbcr(img) #y2 = self._embed(y, encoded, k) #cb = self._embed(cb, encoded, k) #cr = self._embed(cr, encoded, k) #y2 = rescale_intensity(y2, out_range = (numpy.min(y), numpy.max(y))) #Cb2 = rescale_intensity(Cb2, out_range = (numpy.min(Cb), numpy.max(Cb))) #Cr2 = rescale_intensity(Cr2, out_range = (numpy.min(Cr), numpy.max(Cr))) #output = ycbcr_to_rgb(y2, cb, cr) else: raise TypeError("img must be a 2d or 3d array") #if tv_denoising_weight > 0: # output = tv_denoise(output, tv_denoising_weight) if rescale: output = rescale_intensity(output, out_range = (numpy.min(img), numpy.max(img))) #return toimage(output,cmin=0,cmax=255) return output def _extract(self, img): cA, (cH, cV, cD) = dwt2(img.astype(float), self.mother) vec = self._interleave(cH, cV, cD) chunk_size = vec.size // self.total_bits seq0, seq1 = self._generate_sequences(chunk_size) byte = 0 output = bytearray() for i in range(self.total_bits): offset = i * chunk_size chunk = vec[offset: offset + chunk_size] #chunk = vec[i:self.total_bits*chunk_size:self.total_bits] corr0, _ = pearsonr(chunk, seq0) corr1, _ = pearsonr(chunk, seq1) bit = int(corr1 > corr0) byte = (byte << 1) | bit if i % 8 == 7: output.append(byte) byte = 0 return output def _try_decode(self, payload): try: return self.rscodec.decode(payload) except ReedSolomonError: rpayload = bytearray(b ^ 255 for b in payload) return self.rscodec.decode(rpayload) def extract(self, img): if img.ndim == 2: return self._try_decode(self._extract(img)) elif img.ndim == 3: for i in range(img.shape[2]): try: return self._try_decode(self._extract(img[:,:,i])) except ReedSolomonError: pass return self._try_decode(self._extract(mean(img, 2))) else: raise TypeError("img must be a 2d or 3d array")
class Watermarker(object): def __init__(self, max_payload, ec_bytes, seed = 1895746671, mother = "bior3.1", sparsity = 0.7): self.mother = mother self.sparsity = sparsity self.rscodec = RSCodec(ec_bytes) self.max_payload = max_payload self.total_bits = (max_payload + ec_bytes) * 8 self.seed = seed @classmethod def _interleave(cls, cH, cV, cD): vec = numpy.zeros(cH.size + cV.size + cD.size, dtype = float) vec[0::3] = cH.ravel() vec[1::3] = cV.ravel() vec[2::3] = cD.ravel() return vec @classmethod def _deinterleave(cls, vec, cH, cV, cD): return vec[0::3].reshape(cH.shape), vec[1::3].reshape(cV.shape), vec[2::3].reshape(cD.shape) def _generate_sequences(self, chunk_size): rand = Random(self.seed) seq0 = numpy.array([int(rand.random() >= self.sparsity) for _ in range(chunk_size)]) seq1 = seq0[::-1] return seq0, seq1 def _embed(self, img, payload, k): cA, (cH, cV, cD) = dwt2(img.astype(float), self.mother) vec = self._interleave(cH, cV, cD) chunk_size = vec.size // self.total_bits sequences = self._generate_sequences(chunk_size) for i, bit in enumerate(iterbits(payload)): offset = i * chunk_size vec[offset : offset + chunk_size] += k * sequences[bit] #vec[i : self.total_bits*chunk_size : self.total_bits] += k * sequences[bit] w, h = img.shape cH2, cV2, cD2 = self._deinterleave(vec, cH, cV, cD) return idwt2((cA, (cH2, cV2, cD2)), self.mother)[:w,:h] def embed(self, img, payload, k = 4, rescale_color = True): if len(payload) > self.max_payload: raise ValueError("payload too long") padded = bytearray(payload) + b"\x00" * (self.max_payload - len(payload)) encoded = self.rscodec.encode(padded) if img.ndim == 2: output = self._embed(img, encoded, k) elif img.ndim == 3: output = numpy.zeros(img.shape, dtype=float) for i in range(img.shape[2]): output[:,:,i] = self._embed(img[:,:,i], encoded, k) else: raise TypeError("img must be a 2d or 3d array") if rescale_color: output = rescale_intensity(output, out_range = (numpy.min(img), numpy.max(img))) return output def _extract(self, img): cA, (cH, cV, cD) = dwt2(img.astype(float), self.mother) vec = self._interleave(cH, cV, cD) chunk_size = vec.size // self.total_bits seq0, seq1 = self._generate_sequences(chunk_size) byte = 0 output = bytearray() for i in range(self.total_bits): offset = i * chunk_size chunk = vec[offset: offset + chunk_size] #chunk = vec[i:self.total_bits*chunk_size:self.total_bits] corr0, _ = pearsonr(chunk, seq0) corr1, _ = pearsonr(chunk, seq1) bit = int(corr1 > corr0) byte = (byte << 1) | bit if i % 8 == 7: output.append(byte) byte = 0 return output def _try_decode(self, payload): try: return self.rscodec.decode(payload) except ReedSolomonError: rpayload = bytearray(b ^ 255 for b in payload) return self.rscodec.decode(rpayload) def extract(self, img): if img.ndim == 2: return self._try_decode(self._extract(img)) elif img.ndim == 3: for i in range(img.shape[2]): try: return self._try_decode(self._extract(img[:,:,i])) except ReedSolomonError: pass return self._try_decode(self._extract(mean(img, 2))) else: raise TypeError("img must be a 2d or 3d array")
class Watermarker(object): EPSILON = 0.001 def __init__(self, max_payload, ec_bytes, seed = 1910819922, mother = "haar"): self.mother = mother self.rscodec = RSCodec(ec_bytes) self.max_payload = max_payload self.total_bits = (max_payload + ec_bytes) * 8 rand = Random(seed) chunk_size = 3000 while True: self.seq0 = numpy.array([int(rand.random() > 0.8) for _ in range(chunk_size)]) self.seq1 = numpy.array([int(rand.random() > 0.75) for _ in range(chunk_size)]) corr, _ = pearsonr(self.seq0, self.seq1) if corr < self.EPSILON: break def _embed(self, img, payload, k): cA, (cH, cV, cD) = dwt2(img, self.mother) target = cD.reshape(cD.size) chunk_size = target.size // self.total_bits sequence_of = (self.seq0[:chunk_size], self.seq1[:chunk_size]) for i, bit in enumerate(iterbits(payload)): seq = sequence_of[bit] #chunk = target[i::self.total_bits][:seq.size] chunk = target[i * chunk_size:i * chunk_size + seq.size] chunk += k * seq return idwt2((cA, (cH, cV, target.reshape(cH.shape))), self.mother)[:img.shape[0],:img.shape[1]] def embed(self, img, payload, k): if len(payload) > self.max_payload: raise ValueError("payload too long") payload = bytearray(payload) + "\x00" * (self.max_payload - len(payload)) encoded = self.rscodec.encode(payload) if len(img.shape) == 2: return self._embed(img, encoded, k) elif len(img.shape) == 3: hsv = rgb2hsv(img) i = 0 hsv[:,:,i] = self._embed(hsv[:,:,i], encoded, k) return hsv2rgb(hsv) else: raise TypeError("img must be a 2d or 3d array") def _extract(self, img): cA, (cH, cV, cD) = dwt2(img, self.mother) target = cD.reshape(cD.size) chunk_size = target.size // self.total_bits seq0 = self.seq0[:chunk_size] seq1 = self.seq1[:chunk_size] byte = 0 output = bytearray() for i in range(self.total_bits): chunk = target[i * chunk_size : (i * chunk_size) + seq0.size] #chunk = target[i::self.total_bits][:seq0.size] #if not all(chunk[i] == chunk[i+1] for i in range(chunk.size-1)): corr0, _ = pearsonr(chunk, seq0) corr1, _ = pearsonr(chunk, seq1) bit = int(corr1 > corr0) #else: # bit = 0 byte = (byte << 1) | bit if i % 8 == 7: output.append(byte) byte = 0 print repr(output) return output def extract(self, img): if len(img.shape) == 2: return self.rscodec.decode(self._extract(img)) elif len(img.shape) == 3: hsv = rgb2hsv(img) return self.rscodec.decode(self._extract(hsv[:,:,0])) else: raise TypeError("img must be a 2d or 3d array")