C++에서 인코딩 해서 보내는 부분. encode_path 함수에서 QString으로 이미지 파일 경로를 받은후 encode_512 함수를 거쳐서 바이트로 리턴됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | inline QByteArray* encode_512(Eigen::Matrix<float,Dynamic,Dynamic> _mat, int rank = 25){ const int SIZE = 512; // B를 근사하는 B'를 만들 수 있도록 사용될 행렬 A, B Eigen::Matrix<float,Dynamic, Dynamic,RowMajor> A; Eigen::Matrix<float,Dynamic, Dynamic,RowMajor> B; A.resize(SIZE,rank); B.resize(rank,SIZE); for(int i = 0 ; i < SIZE ; ++i){ for(int k = 0 ; k < rank ; ++k){ A( i , k ) = _mat(i , k * round(SIZE / rank) ); } } B = (((A.transpose() * A).inverse()) * A.transpose()) * _mat; QByteArray* arr_A = new QByteArray(reinterpret_cast<char*>(A.data()), SIZE * rank * sizeof(float)); QByteArray* arr_B = new QByteArray(reinterpret_cast<char*>(B.data()), SIZE * rank * sizeof(float)); QByteArray* encoded_mat = new QByteArray(); encoded_mat->push_back(*arr_A); encoded_mat->push_back(*arr_B); delete arr_A; delete arr_B; return encoded_mat; } inline QByteArray encode_path(QString _path, int rank = 25){ QImage* img = img_path(_path); Eigen::Matrix<float, Dynamic,Dynamic,RowMajor> R; Eigen::Matrix<float, Dynamic,Dynamic,RowMajor> G; Eigen::Matrix<float, Dynamic,Dynamic,RowMajor> B; R.resize(512,512); G.resize(512,512); B.resize(512,512); for ( int row = 0; row < img->height() ; ++row ) for ( int col = 0; col < img->width(); ++col ) { QColor clrCurrent( img->pixel( row, col ) ); R(row,col) = clrCurrent.red(); G(row,col) = clrCurrent.green(); B(row,col) = clrCurrent.blue(); } QByteArray* arr_R = encode_512(R, rank); QByteArray* arr_G = encode_512(G, rank); QByteArray* arr_B = encode_512(B, rank); QByteArray sum; sum.push_back(*arr_R); sum.push_back(*arr_G); sum.push_back(*arr_B); delete arr_R; delete arr_G; delete arr_B; return sum; } | cs |
파이썬 수신부 : decode512 함수에서 인코딩된 바이너리 형태의 이미지 데이터를 받고 각 RGB채널의 A와 B행렬을 구분해서 디코딩 한후 최종적으로
일반적인 RGB888포멧의 바이너리 이미지 형태로 리턴합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | def decode2D512(Image2D, rank): SIZE = 512 SIZE_OF_FLOAT = 4 A = np.frombuffer(Image2D[ : SIZE * rank * SIZE_OF_FLOAT ] , dtype = np.float32) B = np.frombuffer(Image2D[ SIZE * rank * SIZE_OF_FLOAT : ] , dtype = np.float32) print("A.shape", A.shape) print("B.shape", B.shape) A.resize((512,rank)) B.resize((rank,512)) print("A.shape", A.shape) print("B.shape", B.shape) C = A.dot(B) print("C.shape", C.shape) C = np.where( C > 255, 255, C) C = np.where( C < 0, 0, C) C = C.astype(np.uint8) print("C.shape", C.shape) return C def decode512(img): SIZE = 512; RANK = 100 SIZE_OF_FLOAT = 4 print("img[ : SIZE * RANK * 2 * SIZE_OF_FLOAT ]" , len(img[ : SIZE * RANK * 2 * SIZE_OF_FLOAT ])) print("img[SIZE * RANK * 2 * SIZE_OF_FLOAT : SIZE * RANK * 4 * SIZE_OF_FLOAT ]" , len(img[SIZE * RANK * 2 * SIZE_OF_FLOAT : SIZE * RANK * 4 * SIZE_OF_FLOAT ])) print("img[SIZE * RANK * 4 * SIZE_OF_FLOAT : SIZE * RANK * 6 * SIZE_OF_FLOAT ]" , len(img[SIZE * RANK * 4 * SIZE_OF_FLOAT : SIZE * RANK * 6 * SIZE_OF_FLOAT ])) REncoded = img[ : SIZE * RANK * 2 * SIZE_OF_FLOAT ] GEncoded = img[SIZE * RANK * 2 * SIZE_OF_FLOAT : SIZE * RANK * 4 * SIZE_OF_FLOAT ] BEncoded = img[SIZE * RANK * 4 * SIZE_OF_FLOAT : SIZE * RANK * 6 * SIZE_OF_FLOAT ] R = decode2D512(REncoded, RANK).tobytes(order='F') G = decode2D512(GEncoded, RANK).tobytes(order='F') B = decode2D512(BEncoded, RANK).tobytes(order='F') print("R", len(R)) print("G", len(G)) print("B", len(B)) b_imgTemp = bytearray() for i in range(512 * 512): b_imgTemp += R[i].to_bytes(1, byteorder = 'big') b_imgTemp += G[i].to_bytes(1, byteorder = 'big') b_imgTemp += B[i].to_bytes(1, byteorder = 'big') b_imgTemp = np.array(b_imgTemp) print(b_imgTemp.shape) return b_imgTemp | cs |
아래쪽은 위 파이썬 디코딩 부분을 Qt에서 구현한 부분 입니다. ba_decode 함수에서 바이트 어레이를 받아서 디코딩한후 일반적인 RGB888 형태의 바이너리
이미지로 변환해서 리턴합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | inline QByteArray* decode_512(QByteArray* _img, int rank = 25){ const int SIZE = 512; //B'를 만들기 위해 사용될 행렬 A, B,와 그 결과를 담을 C, 그리고 타입을 Uchar로 바꿔주기 위한 D 선언. Eigen::Matrix<float,Dynamic, Dynamic> A; Eigen::Matrix<float,Dynamic, Dynamic> B; Eigen::Matrix<float,Dynamic, Dynamic> C; Eigen::Matrix<unsigned char,Dynamic, Dynamic> D; A.resize(SIZE,rank); B.resize(rank,SIZE); C.resize(SIZE, SIZE); D.resize(SIZE, SIZE); const int TYPE_SIZE = sizeof(float); QByteArray temp; for (int i = 0 ; i < SIZE ; ++i){ for(int j = 0 ; j < rank ; ++j){ temp.clear(); for(int x = 0 ; x < TYPE_SIZE ; ++x){ temp.append(*(_img->data() + (i * (rank * TYPE_SIZE) ) + (j * TYPE_SIZE) + x )); } A(i , j) = (*(float*)temp.constData()); } } for (int i = 0 ; i < rank ; ++i){ for(int j = 0 ; j < SIZE ; ++j){ temp.clear(); for(int x = 0 ; x < TYPE_SIZE ; ++x){ temp.append(*(_img->data() + (SIZE * rank * TYPE_SIZE) + (i * (SIZE * TYPE_SIZE) ) + (j * TYPE_SIZE) + x )); } B(i , j) = (*(float*)temp.constData()) ; } } C = (A * B); for (int i = 0 ; i < SIZE ; ++i){ for (int j = 0 ; j < SIZE ; ++j){ if (C(i, j) > 255){ C(i,j) = 255; }else if(C(i, j) < 0){ C(i,j) = 0; } } } D = C.cast<unsigned char>(); QByteArray* encoded_mat = new QByteArray( reinterpret_cast<char*>(D.data()), SIZE * SIZE ); return encoded_mat; } inline QByteArray* ba_decode(QByteArray* _data, int rank = 25){ const int SIZE = 512; QByteArray* R = new QByteArray(_data->data() ,SIZE * rank * 2 * sizeof(float)); QByteArray* G = new QByteArray(_data->data() + SIZE * rank * 2 * sizeof(float) ,SIZE * rank * 2 * sizeof(float)); QByteArray* B = new QByteArray(_data->data() + SIZE * rank * 4 * sizeof(float) ,SIZE * rank * 2 * sizeof(float)); QByteArray* decoded_R = new QByteArray(*decode_512(R,rank)) ; QByteArray* decoded_G = new QByteArray(*decode_512(G,rank)); QByteArray* decoded_B = new QByteArray(*decode_512(B,rank)); QByteArray* sum = new QByteArray(); for(int i = 0 ; i < SIZE * SIZE ; ++i){ sum -> push_back(*(decoded_R->data() + i)); sum -> push_back(*(decoded_G->data() + i)); sum -> push_back(*(decoded_B->data() + i)); } delete decoded_R; delete decoded_G; delete decoded_B; delete R; delete G; delete B; delete _data; return sum; } |
'진행중인 프로젝트 > ImageHandler' 카테고리의 다른 글
[Qt5] 사용자 정의(. ui)로 다이얼로그 띄운 부분 (0) | 2019.06.29 |
---|---|
[Qt5] 페인트 이벤트를 받을 수 있는 사용자 정의 위젯 부분 (0) | 2019.06.29 |
[ Linear Algebra ] Data Compression With Low-Rank Approximation (0) | 2019.06.28 |
[ Network ] TCP / IP C++ / Python 소켓통신 파트 (0) | 2019.06.28 |
ImageHandler 0.0.1 Beta Relese. (0) | 2019.06.28 |