Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds image-guided object detection support to OWL-ViT #18891

Closed
wants to merge 49 commits into from

Conversation

unography
Copy link
Contributor

@unography unography commented Sep 4, 2022

This adds support for doing object detection with OWL-ViT using query image(s)

For #18748

cc: @alaradirik

@unography
Copy link
Contributor Author

Hi @alaradirik I added an initial version for the image-guided obj detection. I still have to add tests and some other cleanup, however, I've some doubts right now

  1. Is the handling of query_embedding correct, while doing the mean and finding out the most dissimilar embedding?
  2. How should the postprocessor handle this case, when there are no labels as such for this?
  3. Any other implementation details I may have missed

@HuggingFaceDocBuilderDev

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint.

@unography unography changed the title Adds image-guided object detection support to OWL-ViT [WIP] Adds image-guided object detection support to OWL-ViT Sep 6, 2022
Copy link
Contributor

@alaradirik alaradirik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Dhruv,

Thank you for your contribution! I realized that I accidentally mislead you when discussing the one-shot detection implementation. I thought the query image would be embedded by the unmodified base model (OwlViTModel) but here is the correct method as described in the Appendix A1.7 of the paper:

  • Query image is embedded the same way as the target image is embedded (which you already implemented)
  • query_image_embeds is forward propagated through class and box prediction heads to retrieve the class embeddings and box preds. The goal of retrieving box predictions is to choose one class embedding / prediction such that it is (1) dissimilar from rest of the predicted class embeddings and (2) has a corresponding box prediction that yields a high intersection of union with the query image.

This part corresponds to def embed_image_query() function at line 110 in the original repo over here. You can disregard the query_box_yxyx argument.

  • The selected class_embedding / query_embedding is used to query the target image in the same way text query_embeds are used within OwlViTForObjectDetection. You can see an example in the original repo over here (
    _image_conditioning_py_callback() function)

Hope this helps and sorry for the delay.

src/transformers/models/owlvit/processing_owlvit.py Outdated Show resolved Hide resolved
src/transformers/models/owlvit/processing_owlvit.py Outdated Show resolved Hide resolved
src/transformers/models/owlvit/processing_owlvit.py Outdated Show resolved Hide resolved
src/transformers/models/owlvit/processing_owlvit.py Outdated Show resolved Hide resolved
src/transformers/models/owlvit/modeling_owlvit.py Outdated Show resolved Hide resolved
src/transformers/models/owlvit/modeling_owlvit.py Outdated Show resolved Hide resolved
src/transformers/models/owlvit/modeling_owlvit.py Outdated Show resolved Hide resolved
src/transformers/models/owlvit/modeling_owlvit.py Outdated Show resolved Hide resolved
src/transformers/models/owlvit/modeling_owlvit.py Outdated Show resolved Hide resolved
src/transformers/models/owlvit/modeling_owlvit.py Outdated Show resolved Hide resolved
@unography
Copy link
Contributor Author

Hi @alaradirik, I made the changes as per the review comments, could you check if they're fine?

I'm working on test cases currently. In the file here, is it okay if I reuse pixel_values itself for query_pixel_values?

So the above line would return

return config, pixel_values, input_ids, attention_mask, pixel_values

and be re-used as

config_and_inputs = self.prepare_config_and_inputs()
config, pixel_values, input_ids, attention_mask, query_pixel_values = config_and_inputs

And apart from the test cases, are there any other changes that I need to make?

@alaradirik
Copy link
Contributor

alaradirik commented Sep 7, 2022

Hi @alaradirik, I made the changes as per the review comments, could you check if they're fine?

I'm working on test cases currently. In the file here, is it okay if I reuse pixel_values itself for query_pixel_values?

So the above line would return

return config, pixel_values, input_ids, attention_mask, pixel_values

and be re-used as

config_and_inputs = self.prepare_config_and_inputs()
config, pixel_values, input_ids, attention_mask, query_pixel_values = config_and_inputs

And apart from the test cases, are there any other changes that I need to make?

Hi @unography, thank you for the contribution once again!

As for your question regarding the tests, yes, it'd make sense to return config, pixel_values, input_ids, attention_mask, pixel_values with OwlViTForObjectDetectionTester.prepare_config_and_inputs().

We can add a line to this function to create query_pixel_values as follows:
query_pixel_values = floats_tensor([self.batch_size, self.num_channels, self.query_image_size, self.query_image_size])

Copy link
Contributor

@alaradirik alaradirik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes look good to me!

There are a few issues that needs to be addressed regarding a missing one-shot detection algorithm detail and state arguments left over from previous commits (from other PRs). Let me know if you have any questions.

src/transformers/models/owlvit/modeling_owlvit.py Outdated Show resolved Hide resolved
@@ -1167,6 +1174,7 @@ def forward(

class OwlViTForObjectDetection(OwlViTPreTrainedModel):
config_class = OwlViTConfig
main_input_name = "pixel_values"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this line caused test errors previously, will need to double check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by default I think the main_input_name is input_ids. Before when it was just text guided detection, the first param was input_ids, and then pixel_values. Now, since input_ids can be None, I made pixel_values as the first param, which is why the test case was failing. Hence this change

Copy link
Contributor

@alaradirik alaradirik Sep 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense! I'd comment out the slow flags (tests with @slow decoraters are skipped) within tests/test_modeling_common.py and run all tests to double check this.

You can run the tests from the root of transformers repo as follows:

# All tests
pytest tests/models/owlvit/test_modeling_owlvit.py
# Run only integration tests
pytest tests/models/owlvit/test_modeling_owlvit.py::OwlViTModelIntegrationTest
# Run a single test
pytest tests/models/owlvit/test_modeling_owlvit.py::OwlViTModelIntegrationTest::test_inference

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is too much of a breaking change, even for a newly released model.

src/transformers/models/owlvit/modeling_owlvit.py Outdated Show resolved Hide resolved
src/transformers/models/owlvit/modeling_owlvit.py Outdated Show resolved Hide resolved
tests/models/owlvit/test_modeling_owlvit.py Outdated Show resolved Hide resolved
Copy link
Contributor

@alaradirik alaradirik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the contribution once again! The code seems to be in great shape and I just left a couple of comments regarding minor style corrections and docstrings.

The only issue is the following tests fail:

  • OwlViTVisionModelTest.test_model
  • OwlViTVisionModelTest.test_model_outputs_equivalence
  • OwlViTModelTest.test_model_outputs_equivalence

I believe this is due to making pixel_values the main argument in OwlViTForObjectDetection.forward() but I couldn't pinpoint the exact issue. @ydshieh could you take a look at the test scripts when you have time?

src/transformers/models/owlvit/modeling_owlvit.py Outdated Show resolved Hide resolved
src/transformers/models/owlvit/modeling_owlvit.py Outdated Show resolved Hide resolved
src/transformers/models/owlvit/modeling_owlvit.py Outdated Show resolved Hide resolved
src/transformers/models/owlvit/modeling_owlvit.py Outdated Show resolved Hide resolved
@ydshieh
Copy link
Collaborator

ydshieh commented Sep 16, 2022

Thank you for the contribution once again! The code seems to be in great shape and I just left a couple of comments regarding minor style corrections and docstrings.

The only issue is the following tests fail:

  • OwlViTVisionModelTest.test_model
  • OwlViTVisionModelTest.test_model_outputs_equivalence
  • OwlViTModelTest.test_model_outputs_equivalence

I believe this is due to making pixel_values the main argument in OwlViTForObjectDetection.forward() but I couldn't pinpoint the exact issue. @ydshieh could you take a look at the test scripts when you have time?

Hi, I couldn't see any test being run by CI. Could you share the error messges?

@unography Could you follow the instruction below to refresh your CircleCI permission
https://support.circleci.com/hc/en-us/articles/360048210711-How-to-Refresh-User-Permissions-
so that the CI could be triggered. Thanks.

@unography
Copy link
Contributor Author

Sure @alaradirik , I'll go through the review comments and make the changes. And actually, on my local, I'm able to get the test cases passed, on running

RUN_SLOW=1 pytest tests/models/owlvit/test_modeling_owlvit.py

I'll check once more

Hi @ydshieh , I'm not able to refresh the permission for some reason, I get an error Something Unexpected Happened on going to https://app.circleci.com/settings/user
I don't have a CircleCI account linked to my Github actually, not sure how to reset the token and run the tests

@alaradirik
Copy link
Contributor

alaradirik commented Sep 16, 2022

Hi, I couldn't see any test being run by CI. Could you share the error messges?

@ydshieh, of course, here is the full error log. return_dict argument is causing the errors but there hasn't been any changes in the modeling or test files to cause this error.

―――――――――――――――――――――――――――――――――――――――――――――― OwlViTVisionModelTest.test_model ――――――――――――――――――――――――――――――――――――――――――――――

self = <tests.models.owlvit.test_modeling_owlvit.OwlViTVisionModelTest testMethod=test_model>

    def test_model(self):
        config_and_inputs = self.model_tester.prepare_config_and_inputs()
>       self.model_tester.create_and_check_model(*config_and_inputs)

tests/models/owlvit/test_modeling_owlvit.py:181: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
tests/models/owlvit/test_modeling_owlvit.py:123: in create_and_check_model
    self.parent.assertEqual(result.pooler_output.shape, (self.batch_size, num_patches + 1, self.hidden_size))
E   AssertionError: torch.Size([12, 32]) != (12, 257, 32)

 tests/models/owlvit/test_modeling_owlvit.py ⨯✓s✓                                                               13% █▍        

―――――――――――――――――――――――――――――――――――― OwlViTVisionModelTest.test_model_outputs_equivalence ――――――――――――――――――――――――――――――――――――

self = <tests.models.owlvit.test_modeling_owlvit.OwlViTVisionModelTest testMethod=test_model_outputs_equivalence>

    def test_model_outputs_equivalence(self):
        config, inputs_dict = self.model_tester.prepare_config_and_inputs_for_common()
    
        def set_nan_tensor_to_zero(t):
            t[t != t] = 0
            return t
    
        def check_equivalence(model, tuple_inputs, dict_inputs, additional_kwargs={}):
            with torch.no_grad():
                tuple_output = model(**tuple_inputs, return_dict=False, **additional_kwargs)
                dict_output = model(**dict_inputs, return_dict=True, **additional_kwargs).to_tuple()
    
                def recursive_check(tuple_object, dict_object):
                    if isinstance(tuple_object, (List, Tuple)):
                        for tuple_iterable_value, dict_iterable_value in zip(tuple_object, dict_object):
                            recursive_check(tuple_iterable_value, dict_iterable_value)
                    elif isinstance(tuple_object, Dict):
                        for tuple_iterable_value, dict_iterable_value in zip(
                            tuple_object.values(), dict_object.values()
                        ):
                            recursive_check(tuple_iterable_value, dict_iterable_value)
                    elif tuple_object is None:
                        return
                    else:
                        self.assertTrue(
                            torch.allclose(
                                set_nan_tensor_to_zero(tuple_object), set_nan_tensor_to_zero(dict_object), atol=1e-5
                            ),
                            msg=(
                                "Tuple and dict output are not equal. Difference:"
                                f" {torch.max(torch.abs(tuple_object - dict_object))}. Tuple has `nan`:"
                                f" {torch.isnan(tuple_object).any()} and `inf`: {torch.isinf(tuple_object)}. Dict has"
                                f" `nan`: {torch.isnan(dict_object).any()} and `inf`: {torch.isinf(dict_object)}."
                            ),
                        )
    
                recursive_check(tuple_output, dict_output)
    
        for model_class in self.all_model_classes:
            model = model_class(config)
            model.to(torch_device)
            model.eval()
    
            tuple_inputs = self._prepare_for_class(inputs_dict, model_class)
            dict_inputs = self._prepare_for_class(inputs_dict, model_class)
>           check_equivalence(model, tuple_inputs, dict_inputs)

tests/test_modeling_common.py:1548: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
tests/test_modeling_common.py:1512: in check_equivalence
    tuple_output = model(**tuple_inputs, return_dict=False, **additional_kwargs)
/opt/miniconda3/envs/hf/lib/python3.8/site-packages/torch/nn/modules/module.py:1110: in _call_impl
    return forward_call(*input, **kwargs)
src/transformers/models/owlvit/modeling_owlvit.py:950: in forward
    return self.vision_model(
/opt/miniconda3/envs/hf/lib/python3.8/site-packages/torch/nn/modules/module.py:1110: in _call_impl
    return forward_call(*input, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = OwlViTVisionTransformer(
  (embeddings): OwlViTVisionEmbeddings(
    (patch_embedding): Conv2d(3, 32, kernel_size=(2, ..., elementwise_affine=True)
      )
    )
  )
  (post_layernorm): LayerNorm((32,), eps=1e-05, elementwise_affine=True)
)
pixel_values = tensor([[[[0.6554, 0.4061, 0.0338,  ..., 0.4825, 0.8356, 0.8248],
          [0.3508, 0.3514, 0.2522,  ..., 0.1101, 0.8...07, 0.7844, 0.0197,  ..., 0.9217, 0.2872, 0.7545],
          [0.6380, 0.8504, 0.1550,  ..., 0.4501, 0.0423, 0.5167]]]])
output_attentions = False, output_hidden_states = False, return_dict = False

    @add_start_docstrings_to_model_forward(OWLVIT_VISION_INPUTS_DOCSTRING)
    @replace_return_docstrings(output_type=BaseModelOutputWithPooling, config_class=OwlViTVisionConfig)
    def forward(
        self,
        pixel_values: torch.FloatTensor,
        output_attentions: Optional[bool] = None,
        output_hidden_states: Optional[bool] = None,
        return_dict: Optional[bool] = None,
    ) -> Union[Tuple, BaseModelOutputWithPooling]:
        r"""
        Returns:
    
        """
        output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
        output_hidden_states = (
            output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
        )
        return_dict = return_dict if return_dict is not None else self.config.use_return_dict
    
        hidden_states = self.embeddings(pixel_values)
        hidden_states = self.pre_layernorm(hidden_states)
        encoder_outputs = self.encoder(
            inputs_embeds=hidden_states,
            output_attentions=output_attentions,
            output_hidden_states=output_hidden_states,
            return_dict=return_dict,
        )
    
        last_hidden_state = encoder_outputs[0]
        pooled_output = last_hidden_state[:, 0, :]
        pooled_output = self.post_layernorm(pooled_output)
    
        return BaseModelOutputWithPooling(
            last_hidden_state=last_hidden_state,
            pooler_output=pooled_output,
>           hidden_states=encoder_outputs.hidden_states,
            attentions=encoder_outputs.attentions,
        )
E       AttributeError: 'tuple' object has no attribute 'hidden_states'

src/transformers/models/owlvit/modeling_owlvit.py:903: AttributeError

 tests/models/owlvit/test_modeling_owlvit.py ⨯sssss✓s✓✓✓✓✓ss✓✓✓✓sssss✓✓✓s✓sss✓✓✓✓✓✓✓✓✓✓✓s✓✓✓s✓✓sssss✓s✓✓✓✓✓ss✓✓ 47% ████▋     
                                             ✓✓sssss✓s✓sss✓✓✓✓✓✓✓✓✓s✓s✓✓✓ss✓                                    63% ██████▍   

――――――――――――――――――――――――――――――――――――――― OwlViTModelTest.test_model_outputs_equivalence ―――――――――――――――――――――――――――――――――――――――

self = <tests.models.owlvit.test_modeling_owlvit.OwlViTModelTest testMethod=test_model_outputs_equivalence>

    def test_model_outputs_equivalence(self):
        config, inputs_dict = self.model_tester.prepare_config_and_inputs_for_common()
    
        def set_nan_tensor_to_zero(t):
            t[t != t] = 0
            return t
    
        def check_equivalence(model, tuple_inputs, dict_inputs, additional_kwargs={}):
            with torch.no_grad():
                tuple_output = model(**tuple_inputs, return_dict=False, **additional_kwargs)
                dict_output = model(**dict_inputs, return_dict=True, **additional_kwargs).to_tuple()
    
                def recursive_check(tuple_object, dict_object):
                    if isinstance(tuple_object, (List, Tuple)):
                        for tuple_iterable_value, dict_iterable_value in zip(tuple_object, dict_object):
                            recursive_check(tuple_iterable_value, dict_iterable_value)
                    elif isinstance(tuple_object, Dict):
                        for tuple_iterable_value, dict_iterable_value in zip(
                            tuple_object.values(), dict_object.values()
                        ):
                            recursive_check(tuple_iterable_value, dict_iterable_value)
                    elif tuple_object is None:
                        return
                    else:
                        self.assertTrue(
                            torch.allclose(
                                set_nan_tensor_to_zero(tuple_object), set_nan_tensor_to_zero(dict_object), atol=1e-5
                            ),
                            msg=(
                                "Tuple and dict output are not equal. Difference:"
                                f" {torch.max(torch.abs(tuple_object - dict_object))}. Tuple has `nan`:"
                                f" {torch.isnan(tuple_object).any()} and `inf`: {torch.isinf(tuple_object)}. Dict has"
                                f" `nan`: {torch.isnan(dict_object).any()} and `inf`: {torch.isinf(dict_object)}."
                            ),
                        )
    
                recursive_check(tuple_output, dict_output)
    
        for model_class in self.all_model_classes:
            model = model_class(config)
            model.to(torch_device)
            model.eval()
    
            tuple_inputs = self._prepare_for_class(inputs_dict, model_class)
            dict_inputs = self._prepare_for_class(inputs_dict, model_class)
>           check_equivalence(model, tuple_inputs, dict_inputs)

tests/test_modeling_common.py:1548: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
tests/test_modeling_common.py:1512: in check_equivalence
    tuple_output = model(**tuple_inputs, return_dict=False, **additional_kwargs)
/opt/miniconda3/envs/hf/lib/python3.8/site-packages/torch/nn/modules/module.py:1110: in _call_impl
    return forward_call(*input, **kwargs)
src/transformers/models/owlvit/modeling_owlvit.py:1132: in forward
    vision_outputs = self.vision_model(
/opt/miniconda3/envs/hf/lib/python3.8/site-packages/torch/nn/modules/module.py:1110: in _call_impl
    return forward_call(*input, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = OwlViTVisionTransformer(
  (embeddings): OwlViTVisionEmbeddings(
    (patch_embedding): Conv2d(3, 32, kernel_size=(2, ..., elementwise_affine=True)
      )
    )
  )
  (post_layernorm): LayerNorm((32,), eps=1e-05, elementwise_affine=True)
)
pixel_values = tensor([[[[0.4672, 0.5573, 0.4972,  ..., 0.3060, 0.1213, 0.4710],
          [0.1233, 0.0373, 0.8195,  ..., 0.5669, 0.8...20, 0.2224, 0.6059,  ..., 0.2634, 0.5912, 0.3576],
          [0.1761, 0.1272, 0.9066,  ..., 0.9368, 0.1087, 0.4829]]]])
output_attentions = False, output_hidden_states = False, return_dict = False

    @add_start_docstrings_to_model_forward(OWLVIT_VISION_INPUTS_DOCSTRING)
    @replace_return_docstrings(output_type=BaseModelOutputWithPooling, config_class=OwlViTVisionConfig)
    def forward(
        self,
        pixel_values: torch.FloatTensor,
        output_attentions: Optional[bool] = None,
        output_hidden_states: Optional[bool] = None,
        return_dict: Optional[bool] = None,
    ) -> Union[Tuple, BaseModelOutputWithPooling]:
        r"""
        Returns:
    
        """
        output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
        output_hidden_states = (
            output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
        )
        return_dict = return_dict if return_dict is not None else self.config.use_return_dict
    
        hidden_states = self.embeddings(pixel_values)
        hidden_states = self.pre_layernorm(hidden_states)
        encoder_outputs = self.encoder(
            inputs_embeds=hidden_states,
            output_attentions=output_attentions,
            output_hidden_states=output_hidden_states,
            return_dict=return_dict,
        )
    
        last_hidden_state = encoder_outputs[0]
        pooled_output = last_hidden_state[:, 0, :]
        pooled_output = self.post_layernorm(pooled_output)
    
        return BaseModelOutputWithPooling(
            last_hidden_state=last_hidden_state,
            pooler_output=pooled_output,
>           hidden_states=encoder_outputs.hidden_states,
            attentions=encoder_outputs.attentions,
        )
E       AttributeError: 'tuple' object has no attribute 'hidden_states'

src/transformers/models/owlvit/modeling_owlvit.py:903: AttributeError

@ydshieh
Copy link
Collaborator

ydshieh commented Sep 16, 2022

@alaradirik

https://github.com/huggingface/transformers/blob/bb61e30962c0a6cf866e7e8e5a75b7d86d8589c2/src/transformers/models/owlvit/modeling_owlvit.py

From the file, it looks like the latest version in this PR is different from the version that produced the error you provided above.

See

if not return_dict:
return (last_hidden_state, pooled_output) + encoder_outputs[1:]
return BaseModelOutputWithPooling(
last_hidden_state=last_hidden_state,
pooler_output=pooled_output,
hidden_states=encoder_outputs.hidden_states,
attentions=encoder_outputs.attentions,
)

where there is

        if not return_dict:
            return (last_hidden_state, pooled_output) + encoder_outputs[1:]

but not in your error message.

@ydshieh
Copy link
Collaborator

ydshieh commented Sep 16, 2022

Sure @alaradirik , I'll go through the review comments and make the changes. And actually, on my local, I'm able to get the test cases passed, on running

RUN_SLOW=1 pytest tests/models/owlvit/test_modeling_owlvit.py

I'll check once more

Hi @ydshieh , I'm not able to refresh the permission for some reason, I get an error Something Unexpected Happened on going to https://app.circleci.com/settings/user I don't have a CircleCI account linked to my Github actually, not sure how to reset the token and run the tests

I triggered it :)

@alaradirik
Copy link
Contributor

@ydshieh great, thank you! I hadn't pulled the latest changes on this branch.

@unography we can merge this PR once the remaining minor issues are addressed, thank you again for the clean implementation :)

@unography unography marked this pull request as ready for review September 25, 2022 10:19
@unography unography changed the title [WIP] Adds image-guided object detection support to OWL-ViT Adds image-guided object detection support to OWL-ViT Sep 25, 2022
@alaradirik alaradirik force-pushed the img_guided_obj_det branch 2 times, most recently from 9ebd950 to bb61e30 Compare November 9, 2022 10:29
@unography
Copy link
Contributor Author

Hi @alaradirik, sorry my notifications got messed up, I was able to go through the comments only now. Do I need to change anything for merging? Upstream url or anything else?

@alaradirik
Copy link
Contributor

Hi @alaradirik, sorry my notifications got messed up, I was able to go through the comments only now. Do I need to change anything for merging? Upstream url or anything else?

Hey @unography no problem at all! I'm about to merge a clean PR with the correct upstream. Could you give me your email address so that I can add you as the co-author to my commits?

@unography
Copy link
Contributor Author

@alaradirik sure, this is my email - k4r4n.dhruv@gmail.com

@github-actions
Copy link

github-actions bot commented Dec 9, 2022

This issue has been automatically marked as stale because it has not had recent activity. If you think this still needs to be addressed please comment on this thread.

Please note that issues that do not follow the contributing guidelines are likely to be ignored.

@alaradirik alaradirik closed this Dec 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants