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 > 255255, 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;
 
}
 

cs


+ Recent posts