Ask Your Question
0

Save list of elements into an image without pixel distortion

asked 2015-08-20 11:01:10 -0600

Enyzrah gravatar image

updated 2015-08-22 10:50:37 -0600

theodore gravatar image
  • I'm doing a c#-EmguCV project related to invisible image watermarking.
  • Is there any OpenCV function / combination of functions to save a map of elements like [{a,b},{b,d},{r.g}........{t,j}] into an image without affecting any of its pixel values?
edit retag flag offensive close merge delete

Comments

I think what you are looking for is steganography. If you search in the web you can find solutions regarding steganography and opencv library. From a quick research you will need to modify the LSB of a pixel values in order to embed the secret information. You can either do it in the initial spatial (aka. RGB) domain, or in another domain (e.g. DCT). However, have in mind that both techniques are lossy approaches.

theodore gravatar imagetheodore ( 2015-08-20 12:57:12 -0600 )edit

Thanks for the response! but Steganography will modify original pixels , I need to save additional information which should't change original pixel values. I'm afraid that i can't explain the whole purpose of my project in one comment. I need the original values of pixels in future to compare the suspicious image and my original watermarked image. Hence i need a way to store a list of elements into my image in a non-removable way.

Enyzrah gravatar imageEnyzrah ( 2015-08-20 21:51:47 -0600 )edit

I do not think that this is possible. For example from what you are describing you need to add an extra channel to your image, where you are gonna store the additional info/data. However, I cannot see how this will not affect the output of your original RGB image. However, if someone knows a way I would interested to hear about it.

theodore gravatar imagetheodore ( 2015-08-21 03:09:50 -0600 )edit

As far i have searched there is no possible way to do :( But i require a way to save the embedded places of my cover image in some sort of place into the same image.hence i can extract it and prove ownership.Would be appreciable if you can suggest any other way to do so.

Enyzrah gravatar imageEnyzrah ( 2015-08-21 04:09:17 -0600 )edit
3

then as I said steganography is the way to go. Searching a bit I found this paper which proposes a lossless method compared to other techniques. Have a look at it, it is also quite recent. Otherwise from the traditional existing methods, embedding the extra data in the dct domain seems to be less lossy compared to the spatial domain.

theodore gravatar imagetheodore ( 2015-08-21 04:14:52 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
4

answered 2015-08-22 10:48:29 -0600

theodore gravatar image

updated 2015-08-22 10:49:20 -0600

finding some time and motivated from an example at the Instant Opencv Starter book here is an example applying steganography in spatial domain by modifying the LSB values of the pixels.

// function applies steganography in spatial domain
void steganograph(Mat &aFrontImage, Mat &aHiddenImage)
{
    // check if two images are the same type and size
    CV_Assert(aFrontImage.type() == aHiddenImage.type() && aFrontImage.size() == aHiddenImage.size());

    // create our stego image, where we are gonna store the final result
    Mat aStegedImage(aFrontImage.rows, aFrontImage.cols, aFrontImage.type());
    // create some temp images that we are gonna need later for the process
    Mat tFront_image, tHidden_image;

    if(aFrontImage.channels() == 3) // check if we are dealing with color images
    {
        // populate mask matrices with the value 0xF0 or 11110000 in binary
        Mat front_mask(aFrontImage.rows, aFrontImage.cols, aFrontImage.type(), Scalar(0xF0, 0xF0, 0xF0));
        Mat hidden_mask(aHiddenImage.rows, aHiddenImage.cols, aHiddenImage.type(), Scalar(0xF0, 0xF0, 0xF0));

        // perform bitwise ANDing of two matrices and store the result in a third matrix.
        // What we achieved with this operation? Well, now the resulting tFront_image and
        // tHidden_image matrices contains only the first four important bits of each pixel
        // in aFrontImage. The remaining four bits are zero padded
        bitwise_and(aFrontImage, front_mask, tFront_image);
        bitwise_and(aHiddenImage, hidden_mask, tHidden_image);

        for(int j = 0; j < aHiddenImage.rows; j++)
            for(int i = 0; i < aHiddenImage.cols; i++)
            {
                // right-shift the pixel components of the tHidden_image matrix by 4 bits,
                // and hence the first four bits are zero padded.
                tHidden_image.at<Vec3b>(j,i)[0] = tHidden_image.at<Vec3b>(j,i)[0] >> 4;
                tHidden_image.at<Vec3b>(j,i)[1] = tHidden_image.at<Vec3b>(j,i)[1] >> 4;
                tHidden_image.at<Vec3b>(j,i)[2] = tHidden_image.at<Vec3b>(j,i)[2] >> 4;
            }
    }else if(aFrontImage.channels() == 1){ // check if we are dealing with grayscale images
        Mat front_mask(aFrontImage.rows, aFrontImage.cols, aFrontImage.type(), Scalar(0xF0));
        Mat hidden_mask(aHiddenImage.rows, aHiddenImage.cols, aHiddenImage.type(), Scalar(0xF0));

        bitwise_and(aFrontImage, front_mask, tFront_image);
        bitwise_and(aHiddenImage, hidden_mask, tHidden_image);

        for(int j = 0; j < aHiddenImage.rows; j++)
            for(int i = 0; i < aHiddenImage.cols; i++)
            {
                tHidden_image.at<uchar>(j,i) = tHidden_image.at<uchar>(j,i) >> 4;
            }
    }

    // Finally, perform the bitwise addition of the tFront_image and tHidden_image matrices
    // to obtain aStegedImage, which is our steganograph image
    bitwise_or(tFront_image, tHidden_image, aStegedImage);

    // save and show the stego image
    imwrite("stegedImg.png", aStegedImage);
    imshow("aStegedImg", aStegedImage);
}

// function to desteganograph an image
void deSteganograph(Mat &aStegedImage)
{
    // create matrices to store the results
    Mat aFrontImage(aStegedImage.rows, aStegedImage.cols, aStegedImage.type());
    Mat aHiddenImage(aStegedImage.rows, aStegedImage.cols, aStegedImage.type());

//    Mat tFront_image, tHidden_image;

    if(aFrontImage.channels() == 3) // check if we are dealing with color images
    {
        // populate again the mask matrices with the values 0xF0 or 11110000 in binary
        // and 0x0F or 00001111 in binary depending which image we want to retrieve
        Mat front_mask(aStegedImage.rows, aStegedImage.cols, aStegedImage.type(), Scalar(0xF0, 0xF0, 0xF0));
        Mat hidden_mask(aStegedImage.rows, aStegedImage.cols, aStegedImage.type(), Scalar(0x0F, 0x0F, 0x0F));

        // apply again bitwise_ANDing to retrieve the images
        bitwise_and(aStegedImage, front_mask, aFrontImage);
        bitwise_and(aStegedImage, hidden_mask, aHiddenImage);

        for(int j = 0; j < aHiddenImage.rows; j++)
            for(int ...
(more)
edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2015-08-20 11:00:00 -0600

Seen: 622 times

Last updated: Aug 22 '15