Cross origin issues when calling `toPixels` in chrome extension.

986 views
Skip to first unread message

Dan Oved

unread,
Jun 4, 2018, 10:27:55 PM6/4/18
to TensorFlow.js Discussion
I want to build a chrome extension that can feed any image from a webpage through a tfjs network.  The extension would search the page for any image element then allow the images to be read for inference.

As the first part of this step, in a content script in the chrome extension, I need to convert the image to pixels with tf.fromPixels(image).  Occasionally, the image comes from a cross-origin url.

When calling tf.fromPixels(image) from within the content script, an error occurs:

"DOMException: Failed to execute 'texImage2D' on 'WebGL2RenderingContext': The image element contains cross-origin data, and may not be loaded."

Has anyone ever gotten around this?  Are there any examples where cross-image origins image reading works in a chrome extension?

FYI my manifest.json looks like:

{
 
"manifest_version": 2,


 
"name": "tfjs extension",
 
"description": "Chrome Extension, TypeScript, Visual Studio Code",
 
"version": "1.0",


 
"content_scripts": [
     
{
         
"matches": ["<all_urls>"],
         
"js": ["js/content_script.js"]
     
}
 
]


 
"permissions": [
   
"activeTab"
 
]
}

Nikhil Thorat

unread,
Jun 4, 2018, 10:35:48 PM6/4/18
to ove...@gmail.com, TensorFlow.js Discussion
Hi Dan,

CORS can be tricky, check out this post on CORS with image reads in WebGL: https://webglfundamentals.org/webgl/lessons/webgl-cors-permission.html

TLDR: you need to make sure the right HTTP headers are set (Access-Control-Allow-Origin) / possibly set the "crossOrigin" attribute on the <img> tag.

--
You received this message because you are subscribed to the Google Groups "TensorFlow.js Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tfjs+uns...@tensorflow.org.
Visit this group at https://groups.google.com/a/tensorflow.org/group/tfjs/.
To view this discussion on the web visit https://groups.google.com/a/tensorflow.org/d/msgid/tfjs/5d2f613e-2de3-4b81-8bfd-e95805997c62%40tensorflow.org.

Dan Oved

unread,
Jun 4, 2018, 10:37:54 PM6/4/18
to TensorFlow.js Discussion, ove...@gmail.com
I see.  This would be for a third party site, of which the server that hosts the image is not accessible, so guess that wouldn't be possible.  

Laurent Denoue

unread,
Jun 5, 2018, 9:53:38 AM6/5/18
to Dan Oved, TensorFlow.js Discussion
can't you download the images yourself from the extension, then process them?

To unsubscribe from this group and stop receiving emails from it, send an email to tfjs+unsubscribe@tensorflow.org.

Nikhil Thorat

unread,
Jun 5, 2018, 10:08:50 AM6/5/18
to lde...@gmail.com, ove...@gmail.com, TensorFlow.js Discussion
Yeah, if you can host it yourself by downloading and reuploading you should be able to read the pixels.

--
You received this message because you are subscribed to the Google Groups "TensorFlow.js Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tfjs+uns...@tensorflow.org.
Visit this group at https://groups.google.com/a/tensorflow.org/group/tfjs/.

Laurent Denoue

unread,
Jun 5, 2018, 10:29:12 AM6/5/18
to Nikhil Thorat, Dan Oved, TensorFlow.js Discussion
Can't we just:
- download the image using the extension
- draw it to a canvas
- pass the canvas to tf.fromPixels



To unsubscribe from this group and stop receiving emails from it, send an email to tfjs+unsubscribe@tensorflow.org.

--
You received this message because you are subscribed to the Google Groups "TensorFlow.js Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tfjs+unsubscribe@tensorflow.org.

Dan Oved

unread,
Jun 5, 2018, 10:42:41 AM6/5/18
to TensorFlow.js Discussion, nsth...@google.com, ove...@gmail.com
I've tried something that creates another image element and "downloads" it by setting the src:

function reloadImage(image: HTMLImageElement) {
 
const copiedImage = new Image();

 
return new Promise((resolve, reject) => {
    copiedImage
.onload = () => {
      resolve
(copiedImage);
   
}

    copiedImage
.crossOrigin = 'anonymous';

    copiedImage
.src = image.src;
 
})
}


async
function toTensor(element: HTMLImageElement) {
 
const image = await reloadImage(element);

 
const tensor = tf.fromPixels(image);

 
return tensor;
}

and get the same error.

Then I tried also rendering to canvas and getting the image data:

function loadImageData(image: HTMLImageElement) {
 
const canvas = document.createElement('canvas');
 
const context = canvas.getContext('2d');
  canvas
.width = image.width;
  canvas
.height = image.height;
  context
.drawImage(image, 0, 0 );
 
return context.getImageData(0, 0, image.width, image.height);
}


async
function toTensor(element: HTMLImageElement) {
 
const imageData = await loadImageData(element);

 
const tensor = tf.fromPixels(element);

 
return tensor;
}

And I get an error:

DOMException: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.

--
You received this message because you are subscribed to the Google Groups "TensorFlow.js Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tfjs+uns...@tensorflow.org.
Visit this group at https://groups.google.com/a/tensorflow.org/group/tfjs/.

Laurent Denoue

unread,
Jun 5, 2018, 10:45:38 AM6/5/18
to Dan Oved, TensorFlow.js Discussion, Nikhil Thorat
yes, it makes sense that setting the same URL to a new IMG (even if painting after to a CANVAS) fails.

I think you need to really download the image to disk from the extension, then load it back into a new image.

Laurent

To unsubscribe from this group and stop receiving emails from it, send an email to tfjs+unsubscribe@tensorflow.org.

Dan Oved

unread,
Jun 5, 2018, 10:46:52 AM6/5/18
to TensorFlow.js Discussion
For the record, I'm trying to run this extension while browsing wikiart.org to run tfjs models on wiki art images.


The images on that side have headers Access-Control-Allow-Origin: * so I believe it's something to do with the chrome extension config.

Dan Oved

unread,
Jun 5, 2018, 11:39:10 AM6/5/18
to TensorFlow.js Discussion
Ok I got it working by following this stackoverflow answer:


When granting cross-origin permissions via the "permissions" in the manifest.json, this is granted to the background script.  So I have the content script send a message with the url to the background script, and it does the processing, sending a response back.  This works:

In the content script:

    chrome.runtime.sendMessage({url: element.src}, function(response) {
      console
.log(response.result);
   
});

In background page script:

async function loadImage(url: string): Promise<HTMLImageElement> {
 
const image = new Image();

 
return new Promise((resolve: (HTMLImageElement) => void, reject) => {
    image
.onload = () => { resolve(image) }

    image
.src = url;
 
});
}


async
function toTensor(url: string) {
 
const image = await loadImage(url);

 
const tensor = tf.fromPixels(image);

 
return tensor;
}



chrome
.runtime.onMessage.addListener((request, sender, sendResponse) => {
 
if (request.url) {
   
const imageTensor = toTensor(request.url);

    sendResponse
({result: 'loaded'});
 
}
});

Laurent Denoue

unread,
Jun 5, 2018, 12:54:41 PM6/5/18
to Dan Oved, TensorFlow.js Discussion
👍
--
You received this message because you are subscribed to the Google Groups "TensorFlow.js Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tfjs+uns...@tensorflow.org.
Visit this group at https://groups.google.com/a/tensorflow.org/group/tfjs/.
Reply all
Reply to author
Forward
0 new messages