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

Copy cv.QueryFrame() into freshly created image #423

Merged
merged 1 commit into from Apr 19, 2013

Conversation

mfkaptan
Copy link
Contributor

Due to every cv.QueryFrame() modifies the same memory area we have
to use cv.CreateImage() and copy our cv.QueryFrame() into it. This
should fix the issue #96.

Due to every cv.QueryFrame() modifies the same memory area we have
to use cv.CreateImage() and copy our cv.QueryFrame() into it. This
should fix the issue sightmachine#96.
@jayrambhia
Copy link
Contributor

Instead of copying frame in VirtualCamera, the copy should be made in Image while creating it. Because if this problem happens with VirtualCamera, it will also happen with Camera and all other utilities. Even creating a simple Image from cv2.cv.iplimage will create this problem. Okay. I think I checked it with Camera, it doesn't happen. But this still happens.

img = Image("lenna")
cvimg = img.getBitmap()

img1 = Image(cvimg)
cv2.cv.Threshold(cvimg, cvimg, 128, 255, cv2.cv.CV_THRESH_BINARY)

img2 = Image(cvimg)

img1.show()
img2.show() # Different images.

n1 = img1.getNumpy()
n2 = img2.getNumpy()
n3 = img.getNumpy()

from numpy import array_equal
print array_equal(n1, n2) # True
print array_equal(n1, n3) # True
print array_equal(n3, n2) # True

So, I think rather than making copies in each utility, the copy should be made when the image is created.

@kscottz
Copy link
Contributor

kscottz commented Apr 19, 2013

I am going to go ahead and merge this in. Thanks!

kscottz pushed a commit that referenced this pull request Apr 19, 2013
Copy cv.QueryFrame() into freshly created image
@kscottz kscottz merged commit dc87d63 into sightmachine:develop Apr 19, 2013
@jayrambhia
Copy link
Contributor

@kscottz This doesn't solve the real problem. It's just a workaround to get VirtualCamera working. We should make a copy of bitmap image while creating new Image.

@kscottz
Copy link
Contributor

kscottz commented Apr 19, 2013

This seems right to me. Is cv.copy not doing a deep copy? My understanding is that not doing a deep copy from the video frame buffer is the problem right?

@jayrambhia
Copy link
Contributor

cv.Copy makes deepcopy. but this problem is a big one. It happens with everything. As I have provided the example, simple Image loading with iplimage has this problem. So I was saying, if we make copy of the source while creating the Image by using cv.Copy, this problem would cease to exist. Now, we don't have to make copies in individual utilities, just making the copy of the source while creating the Image object would work.

@kscottz
Copy link
Contributor

kscottz commented Apr 19, 2013

oooooooooooooooh I think I see it. Basically we're not doing the deep copy when we take in an IplImage to the ImageClass constructor? Does this example get at the heart of the problem?

foo # This is an iplimage
a = Image(foo)
b = Image(foo) 
a = a.edges()
# b is now also edges

@jayrambhia
Copy link
Contributor

Yeah, you are correct. but this example isn't right. Here, since you're doing a = a.edges(), you're creating a new object and not changing the original iplimage source. if you change the iplimage source foo, both images will have change.

@jayrambhia
Copy link
Contributor

@kscottz I found another referencing problem.

img = Image("lenna")
cvimg = img.geBitmap()
cv2.cv.Threshold(cvimg, cvimg, 128, 255, cv2.cv.CV_THRESH_BINARY) # change cvimg
a = img.getNumpy() # totally changed.

But this works

img = Image("lenna")
cvimg = img.getBitmap()
b = img.getNumpy()
cv2.cv.Threshold(cvimg, cvimg, 128, 255, cv2.cv.CV_THRESH_BINARY) # change cvimg
a = img.getNumpy() # no change at all.

So, when you once call Image.getNumpy(), it creates numpy array from cv2.cv.iplimage and when called again simply returns the numpy buffer. But when cv2.cv.iplimage (_bitmap) image is modified initially, getNumpy() call crates numpy from the modified iplimage source. I think when returning Bitmap, numpy arrays, we should really return a copy of the corresponding variable.

@ozancaglayan
Copy link

This is how it is done in Camera.getImage() (Line 588):

frame = cv.RetrieveFrame(self.capture)                                  
newimg = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_8U, 3)
cv.Copy(frame, newimg)                                                  
return Image(newimg, self)

@kscottz
Copy link
Contributor

kscottz commented Apr 19, 2013

@jayrambhia First example is out of our domain. Calling getBitmap really should be a protected method. Second example is numpy caching, we're never going to catch that either. Reminds me of an old joke

@jayrambhia
Copy link
Contributor

@kscottz so I tried returning copies of bitmap, cvmat, numpy, etc https://github.com/jayrambhia/SimpleCV/compare/Main;referncing_issues and I got so many broken tests.. https://gist.github.com/jayrambhia/5423271 . So I'm just going to leave this alone as of now. But we should totally make a copy of iplimage while creating a new Image object.

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.

None yet

4 participants